C# 任务列表没有给出我所期望的
当我运行以下命令时,我得到Task#{0}和cb的值100 如果我在循环中逐行调试,那么我会得到正确的答案 如何解决这个问题C# 任务列表没有给出我所期望的,c#,.net,task,C#,.net,Task,当我运行以下命令时,我得到Task#{0}和cb的值100 如果我在循环中逐行调试,那么我会得到正确的答案 如何解决这个问题 public static void TaskList() { ConcurrentBag<int> cb = new ConcurrentBag<int>(); List<Task> taskArray = new List<Task>(); for (int i = 0; i < 100;
public static void TaskList()
{
ConcurrentBag<int> cb = new ConcurrentBag<int>();
List<Task> taskArray = new List<Task>();
for (int i = 0; i < 100; i++)
{
taskArray.Add(Task.Factory.StartNew((Object obj) => {
int j = 0 + i;
cb.Add(j);
Debug.WriteLine("Task #{0} created on {1}",
j, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(10);
},
i));
}
Task.WaitAll(taskArray.ToArray());
foreach(var v in cb)
{
Debug.WriteLine(v);
}
Debug.WriteLine("");
}
publicstaticvoid任务列表()
{
ConcurrentBag cb=新ConcurrentBag();
List taskArray=新列表();
对于(int i=0;i<100;i++)
{
taskArray.Add(Task.Factory.StartNew)((Object obj)=>{
int j=0+i;
cb.添加(j);
WriteLine(“在{1}上创建的任务{0}”),
j、 Thread.CurrentThread.ManagedThreadId);
睡眠(10);
},
i) );
}
Task.WaitAll(taskArray.ToArray());
foreach(cb中的var v)
{
Debug.WriteLine(v);
}
Debug.WriteLine(“”);
}
您正在任务中传递一个修改的闭包(i
)
有效执行任务
时,i
的值不确定(在您的情况下,它是100,因为任务在for
循环完成后开始)
您必须避免在延迟执行的委托中捕获修改过的闭包(您的任务
代码段就是一个例子,但使用IEnumerable
上的LINQ也可能发生同样的情况)
相反,将您的值分配给局部变量,并将其传递到任务中操作:
for (int i = 0; i < 100; i++)
{
var count = i;
taskArray.Add(Task.Factory.StartNew((Object obj) => {
int j = 0 + count;
cb.Add(j);
Debug.WriteLine("Task #{0} created on {1}",
j, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(10);
},
i));
}
for(int i=0;i<100;i++)
{
var计数=i;
taskArray.Add(Task.Factory.StartNew)((Object obj)=>{
int j=0+计数;
cb.添加(j);
WriteLine(“在{1}上创建的任务{0}”),
j、 Thread.CurrentThread.ManagedThreadId);
睡眠(10);
},
i) );
}
您正在任务中传递一个修改的闭包(i
)
有效执行任务
时,i
的值不确定(在您的情况下,它是100,因为任务在for
循环完成后开始)
您必须避免在延迟执行的委托中捕获修改过的闭包(您的任务
代码段就是一个例子,但使用IEnumerable
上的LINQ也可能发生同样的情况)
相反,将您的值分配给局部变量,并将其传递到任务中操作:
for (int i = 0; i < 100; i++)
{
var count = i;
taskArray.Add(Task.Factory.StartNew((Object obj) => {
int j = 0 + count;
cb.Add(j);
Debug.WriteLine("Task #{0} created on {1}",
j, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(10);
},
i));
}
for(int i=0;i<100;i++)
{
var计数=i;
taskArray.Add(Task.Factory.StartNew)((Object obj)=>{
int j=0+计数;
cb.添加(j);
WriteLine(“在{1}上创建的任务{0}”),
j、 Thread.CurrentThread.ManagedThreadId);
睡眠(10);
},
i) );
}
您几乎每次运行都会看到100
打印出来,因为在运行任务时,下一行中的i
相当于100:
int j = 0 + i;
我相信您正试图用int j=0+I
行来缓解这个问题,但是由于I
是正在发生变化的,因此当任务运行时,j
始终等同于I
是什么。如果将i
的值分配给任务之外的j
,则不会看到此问题:
int j = i;
taskArray.Add(Task.Factory.StartNew((Object obj) => {
cb.Add(j);
Console.WriteLine("Task #{0} created on {1}",
j, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(10);
}, , i));
我不确定我是否解释得很好,但我希望它能有所帮助。您几乎每次运行都会看到100
打印出来,因为在运行任务时,下一行中的I
相当于100:
int j = 0 + i;
我相信您正试图用int j=0+I
行来缓解这个问题,但是由于I
是正在发生变化的,因此当任务运行时,j
始终等同于I
是什么。如果将i
的值分配给任务之外的j
,则不会看到此问题:
int j = i;
taskArray.Add(Task.Factory.StartNew((Object obj) => {
cb.Add(j);
Console.WriteLine("Task #{0} created on {1}",
j, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(10);
}, , i));
我不确定我是否解释得很好,但我希望能有所帮助。你为什么需要睡眠?@jdweng我只是在模拟一项需要一些时间的任务。很明显,这项任务不仅仅产生i(好吧,j)。你为什么需要睡眠?@jdweng我只是在模拟一项需要一些时间的任务。很明显,这项任务所做的不仅仅是产生i(好的j)。不确定是谁first@paparazzo费德里科领先我几秒钟。谢谢你的投票:)我不知道是谁first@paparazzo费德里科领先我几秒钟。谢谢你的投票:)