这是我的代码:
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/