Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 任务列表没有给出我所期望的_C#_.net_Task - Fatal编程技术网

C# 任务列表没有给出我所期望的

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;

当我运行以下命令时,我得到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; 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费德里科领先我几秒钟。谢谢你的投票:)