我想我在这里错过了一些基础知识而无法解决问题..
以下程序的输出与预期不符。有人可以帮我理解这个问题。
using System;
using System.Threading;
public class Program
{
private static readonly object _lock = new object();
public static void Main()
{
for (var i = 0; i < 10; i++)
{
//Console.WriteLine("Start "+i);
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
thread.IsBackground = true;
thread.Start();
}
}
private static void ExecuteInBackground(Object obj)
{
lock (_lock)
{
Console.WriteLine("A "+obj);
test.ttt(obj);
}
}
}
public static class test
{
public static void ttt(object obj)
{
Console.WriteLine("B "+ obj);
}
}
我希望在输出中看到0到9 ..但实际输出如下..
A 1
B 1
A 1
B 1
A 3
B 3
A 4
B 4
A 5
B 5
A 6
B 6
A 7
B 7
A 8
B 8
A 9
B 9
A 10
B 10
非常感谢任何帮助。
请随意使用https://dotnetfiddle.net/nYfbMU
中的代码谢谢, 雷迪。
答案 0 :(得分:4)
改变这个:
for (var i = 0; i < 10; i++)
{
//Console.WriteLine("Start "+i);
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
到此:
for (var i = 0; i < 10; i++)
{
var temp = i;
//Console.WriteLine("Start "+i);
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(temp));
这是一个关闭问题。见Why is it bad to use an iteration variable in a lambda expression
原始代码没有按预期工作的原因,以及temp变量为什么会这样,是因为() => ExecuteInBackground(i)
就像在说&#34;在将来的某个时候,我想要这个新代码线程调用ExecuteInBackground
方法,传入任何值进行调用时&#34;。由于循环变量在循环开始时进入范围,并且在循环结束后超出范围,因此i的值在调用Thread的时间和ExecuteInBackground执行时之间发生变化。通过在循环内使用临时变量,循环的每次迭代都超出范围,每个线程对ExecuteInBackground的调用实际上是获得一个不同的变量,每个调用具有不变的值,并且下一次递增i并不会搞砸。
答案 1 :(得分:0)
这对我有用..
using System;
using System.Threading;
public class Program
{
private static readonly object _lock = new object();
public static void Main()
{
for (var i = 0; i <= 10; i++)
{
fn(i);
}
Console.ReadLine();
}
private static void fn(int i)
{
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
thread.IsBackground = true;
thread.Start();
}
private static void ExecuteInBackground(Object obj)
{
lock (_lock)
{
Thread.Sleep(500);
Console.WriteLine("A "+obj);
test.ttt(obj);
}
}
}
public static class test
{
//private static readonly object _lock = new object();
public static void ttt(object obj)
{
//lock(_lock)
Console.WriteLine("B "+ obj);
}
}