启动任务在foreach循环使用上一个项目价值 [英] Starting Tasks In foreach Loop Uses Value of Last Item

查看:159
本文介绍了启动任务在foreach循环使用上一个项目价值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在用新的任务做玩第一次尝试,但事情正在发生,我不明白。

I am making a first attempt at playing with the new Tasks, but something is happening that I don't understand.

首先,code,这是pretty直线前进。我传递的路径一些图像文件的列表,并尝试添加一个任务来处理它们:

First, the code, which is pretty straight-forward. I pass in a list of paths to some image files, and attempt to add a task to process each of them:

public Boolean AddPictures(IList<string> paths)
{
    Boolean result = (paths.Count > 0);
    List<Task> tasks = new List<Task>(paths.Count);

    foreach (string path in paths)
    {
        var task = Task.Factory.StartNew(() =>
            {
                Boolean taskResult = ProcessPicture(path);
                return taskResult;
            });
        task.ContinueWith(t => result &= t.Result);
        tasks.Add(task);
    }

    Task.WaitAll(tasks.ToArray());

    return result;
}

我发现,如果我只让用,说这跑,在单元测试3路径列表,这三个任务使用在提供的列表中的最后一个路径。如果我步(和减慢循环的处理),从该环的每个路径用于

I've found that if I just let this run with, say, a list of 3 paths in a unit test, all three tasks use the last path in the provided list. If I step through (and slow down the processing of the loop), each path from the loop is used.

有人可以请解释发生了什么,为什么?可能的解决方法?

Can somebody please explain what is happening, and why? Possible workarounds?

谢谢,

WTS

Thanks,
wTs

推荐答案

您正在关闭了循环变量。不要那样做。以一个副本,而不是:

You're closing over the loop variable. Don't do that. Take a copy instead:

foreach (string path in paths)
{
    string pathCopy = path;
    var task = Task.Factory.StartNew(() =>
        {
            Boolean taskResult = ProcessPicture(pathCopy);
            return taskResult;
        });
    task.ContinueWith(t => result &= t.Result);
    tasks.Add(task);
}

您当前code是捕获路径 - 不是的的它,当你创建任务,但变量本身。该变量的变化每个你去通过循环时间价值 - 因此它可以很容易地通过您的代理被调用的时候更改

Your current code is capturing path - not the value of it when you create the task, but the variable itself. That variable changes value each time you go through the loop - so it can easily change by the time your delegate is called.

通过采取变量的副本,你引入的新的的变量每次都要经过循环时间 - 当你拍摄的的变量,它不会在循环的下一次迭代来改变。

By taking a copy of the variable, you're introducing a new variable each time you go through the loop - when you capture that variable, it won't be changed in the next iteration of the loop.

埃里克利珀有一对博客文章的其中进入这个在很多更详细:<一href=\"http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx\">part 1 ; <一href=\"http://blogs.msdn.com/b/ericlippert/archive/2009/11/16/closing-over-the-loop-variable-part-two.aspx\">part 2 。

Eric Lippert has a pair of blog posts which go into this in a lot more detail: part 1; part 2.

不要难过 - 这抓住几乎所有人都出来:(

Don't feel bad - this catches almost everyone out :(

这篇关于启动任务在foreach循环使用上一个项目价值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆