C#简单的多线程-为什么不能产生正确的结果?
有人能告诉我为什么下面的结果不正确吗?当我期待0123时,它给了我1233C#简单的多线程-为什么不能产生正确的结果?,c#,multithreading,C#,Multithreading,有人能告诉我为什么下面的结果不正确吗?当我期待0123时,它给了我1233 public static readonly object locker = new object(); public static List<int> queue = new List<int>(); public static void calculate(int input) { Thread.Sleep(1000); loc
public static readonly object locker = new object();
public static List<int> queue = new List<int>();
public static void calculate(int input)
{
Thread.Sleep(1000);
lock (locker)
{
queue.Add(input);
}
}
[TestMethod]
public void TestT()
{
int[] _intList = new int[] { 0, 1, 2, 3 };
List<Thread> _threadList = new List<Thread>();
foreach (int num in _intList)
{
Thread t = new Thread(() => calculate(num));
t.Start();
_threadList.Add(t);
}
foreach (Thread t in _threadList) { t.Join(); }
foreach (var t in queue)
{
Console.WriteLine(t);
}
}
将变量传递给lambda表达式时,它将被表达式捕获。所以这不是一个拷贝,而是你得到的变量。这是foreach和延迟执行(多线程或非多线程)的一个常见问题,因为foreach continues num正在获取它的下一个值,如果它这样做是因为线程要计算,那么将计算该值 如果您没有多线程,而是在foreach之后调用lambda的结果,您将看到的结果将是3,在这种情况下,您只是看到它们的集合为1,因为启动线程所需的时间很可能与1次迭代相同
在创建变量副本时,该变量在foreach的范围内声明,并且每次都是一个新变量,它不会被更改为下一个成员,而该变量就是被捕获的变量,为您提供了正确的结果。这是正确的方法。您得到的结果并非意外,但也不能保证,第一个方法可以得到0 1 2 3到3 3 3之间的任何结果,第二个方法保证正确的输出。当您将变量传递给lambda表达式时,它会被表达式捕获。所以这不是一个拷贝,而是你得到的变量。这是foreach和延迟执行(多线程或非多线程)的一个常见问题,因为foreach continues num正在获取它的下一个值,如果它这样做是因为线程要计算,那么将计算该值 如果您没有多线程,而是在foreach之后调用lambda的结果,您将看到的结果将是3,在这种情况下,您只是看到它们的集合为1,因为启动线程所需的时间很可能与1次迭代相同
在创建变量副本时,该变量在foreach的范围内声明,并且每次都是一个新变量,它不会被更改为下一个成员,而该变量就是被捕获的变量,为您提供了正确的结果。这是正确的方法。您得到的结果并非意外,但也不能保证,第一个方法可以得到0 1 2 3到3 3 3之间的任何结果,第二个方法保证正确的输出。当您将变量传递给lambda表达式时,它会被表达式捕获。所以这不是一个拷贝,而是你得到的变量。这是foreach和延迟执行(多线程或非多线程)的一个常见问题,因为foreach continues num正在获取它的下一个值,如果它这样做是因为线程要计算,那么将计算该值 如果您没有多线程,而是在foreach之后调用lambda的结果,您将看到的结果将是3,在这种情况下,您只是看到它们的集合为1,因为启动线程所需的时间很可能与1次迭代相同
在创建变量副本时,该变量在foreach的范围内声明,并且每次都是一个新变量,它不会被更改为下一个成员,而该变量就是被捕获的变量,为您提供了正确的结果。这是正确的方法。您得到的结果并非意外,但也不能保证,第一个方法可以得到0 1 2 3到3 3 3之间的任何结果,第二个方法保证正确的输出。当您将变量传递给lambda表达式时,它会被表达式捕获。所以这不是一个拷贝,而是你得到的变量。这是foreach和延迟执行(多线程或非多线程)的一个常见问题,因为foreach continues num正在获取它的下一个值,如果它这样做是因为线程要计算,那么将计算该值 如果您没有多线程,而是在foreach之后调用lambda的结果,您将看到的结果将是3,在这种情况下,您只是看到它们的集合为1,因为启动线程所需的时间很可能与1次迭代相同
在创建变量副本时,该变量在foreach的范围内声明,并且每次都是一个新变量,它不会被更改为下一个成员,而该变量就是被捕获的变量,为您提供了正确的结果。这是正确的方法。您得到的结果并非意外,但也不能保证,第一种方法可以得到从0 1 2 3到3 3 3的任何结果,第二种方法保证正确的输出。您编译的是哪个版本的c#?或者你为什么期望结果是0123?线程可以按任何顺序调度…@RonanThibaudau他们改变了foreach循环在5.0中编译的方式compiler@RonanThibaudau是的。你是针对哪个版本的c#编译的?或者你为什么期望结果是0123?线程可以按任何顺序调度…@RonanThibaudau他们改变了foreach循环在5.0中编译的方式compiler@RonanThibaudau是的。你是针对哪个版本的c#编译的?或者你为什么期望结果是0123?线程可以按任何顺序调度…@RonanThibaudau他们改变了foreach循环在5.0中编译的方式compiler@RonanThibaudau是的。你是针对哪个版本的c#编译的?或者你为什么期望结果是0123?线程可以按任何顺序调度…@RonanThibaudau他们改变了foreach循环在5.0中编译的方式compiler@RonanThibaudau赞成。
foreach (int num in _intList)
{
int testNum = num;
Thread t = new Thread(() => calculate(testNum));
t.Start();
_threadList.Add(t);
}