C# 多线程,无重复

标签 c# multithreading duplicates

这是我的代码:

    Thread _th1, _th2, _th3, _th4;
int _i;

    void thMethod()
    {
        while(_i < 100){
            Thread.Sleep((new Random()).Next(1,500));
            Application.DoEvents();
            Console.WriteLine(_i);
            _i++;
        }
    }

    private void button4_Click(object sender, EventArgs e)
    {
        _th1 = new Thread(new ThreadStart(thMethod));
        _th1.Start();
        _th2 = new Thread(new ThreadStart(thMethod));
        _th2.Start();
        _th3 = new Thread(new ThreadStart(thMethod));
        _th3.Start();
        _th4 = new Thread(new ThreadStart(thMethod));
        _th4.Start();
    }

我想做的是, 使用多线程执行 Console.WriteLine 从 0 到 99, 并且延迟是随机的。

但是,我的代码打印重复的数字

嗯,这就是结果。

0 1 2 2 4 5 6 7 8 9 10 10 12 13 14 14 16 16 18 19 20 20 22 22 24 24 26 26 28 28 30 31 32 33 34 35 36 36 38 39 40 40 42 42 44 44 46 46 48 49 50 50 52 52 54 54 56 56 58 58 60 60 62 62 64 65 66 66 68 68 70 70 72 72 74 74 76 76 78 78 80 80 82 82 84 84 86 87 88 88 90 90 92 92 94 94 96 96 98 98 100 101 102

如您所见,打印了重复的数字, 而且它甚至不止于 99。

那么...如何更正此代码以使其正常运行?

======================== 我必须像这样改变吗?

    void thMethod()
    {
        while(_i < 100){
            Thread.Sleep((new Random()).Next(1,500));
            Application.DoEvents();
            Interlocked.Increment(ref _i);
            Console.WriteLine(_i);
        }
    }

这个?

最佳答案

尽管您应该使用其他帖子提到的 Interlocked.Increment 。这不是您遇到的确切问题。

您的数字超过 100 的原因是因为您递增值的行出现在 sleep 之后。这会导致线程进入循环,但当它们写出值时,该值已经更改为 100 以上。

例如t1、t2和t3进入循环并等待500ms,i为99。然后t4退出并将其递增到100,现在t1将打印100,t2将打印101,t3将打印102。

Interlocked.Increment实际上并不能解决问题,因为当值实际写出时,Thread.Sleep仍然会导致不一致。

要解决该问题,您需要使用 thread lock 声明一个要锁定的变量,因为您无法锁定 _i,因为它不是引用类型:

object obj = new object();

void thMethod()
{
    while (_i < 100)
    {
        lock (obj)
        {
            Console.WriteLine(_i);
            _i++;
        }
        Thread.Sleep((new Random()).Next(1, 500));
    }
}

这样您就不会得到重复项,并且该值将停止在 99。

关于C# 多线程,无重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11730236/

相关文章:

java - 如果进程超过分配的时间,如何杀死进程

wpf - 无需额外线程即可防止 UI 卡住

Mysql 关于重复键更新 - 如何使其不插入新行?

c# - Resharper 可以解开包裹的代码行吗?

c# - 当类型不同但兼容比较值时,如何检查值类型装箱对象的相等性

c++ - 我如何 "clear"std::promise?

python - 如何使用 Python 根据有关日期值的条件删除重复项?

.htaccess - 是否可以使用htaccess中的此模式的规范URL:/a/*/id/uniqueid?

c# - 查看EF4生成的查询?

c# - 通过 C# 检索 CRM 中所有帐户的列表?