代码之家  ›  专栏  ›  技术社区  ›  paparazzo

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

  •  0
  • paparazzo  · 技术社区  · 7 年前

    当我运行以下命令时,任务{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("");
    }
    
    2 回复  |  直到 7 年前
        1
  •  3
  •   Federico Dipuma    7 年前

    您正在传递修改的闭包( i )在您的任务中。

    Task 有效执行的价值 未确定(在您的情况下,它是100,因为任务在 for 回路饰面)。

    您必须避免在委托中捕获延迟执行的修改过的闭包(您的 任务 snippet就是一个示例,但在上使用LINQ时也可能发生同样的情况 IEnumerable )。

    相反,将值赋给局部变量,并在 任务 措施:

    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));
    }
    
        2
  •  1
  •   pushasha    7 年前

    你看到了 100 几乎每次跑步都要打印出来,因为 i 在下一行中,当任务运行时等于100:

    int j = 0 + i;
    

    我相信您正试图用您的 int j = 0 + i 但是自从 改变的是什么, j 将始终等同于 是任务运行的时间。如果指定的值为 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));
    

    我不确定我解释得很好,但我希望这能有所帮助。