并行任务的意外输出

Unexpected output on parallel tasks

我必须并行化现有代码。基本上,代码获取一个文件,对其进行处理并将结果保存在一个新文件中。我需要对一批文件进行这项工作。

所以,我做这个示例代码是为了查看我需要什么样的代码结构,但它运行起来很奇怪:

class Program
{
    static void Main(string[] args)
    {
        Processor processor = null;
        ProcessAsync(processor, 3);
    }

    static void ProcessAsync(Processor processor, int n)
    {
        IList<Task> tasks = new List<Task>();

        for (int i = 0; i < n; ++i)
        {
            processor = new Processor(i);
            tasks.Add(new Task(() => processor.Process()));
            tasks[i].Start();
        }

        for (int i = 0; i < n; ++i)
        {
            tasks[i].Wait();
        }
    }
}

class Processor
{
    private readonly int id;

    public Processor(int id)
    {
        this.id = id;
    }

    public void Process()
    {
        Console.WriteLine(id.ToString("000") + ": " + "Processing...");
        Thread.Sleep(1000);
        Console.WriteLine(id.ToString("000") + ": " + "Processed!");
    }
}

我期望这样的输出:

Task 000: Processing...
Task 001: Processing...
Task 002: Processing...
Task 000: Processed!
Task 001: Processed!
Task 002: Processed!

但我得到了这个结果:

Task 002: Processing...
Task 002: Processing...
Task 002: Processing...
Task 002: Processed!
Task 002: Processed!
Task 002: Processed!

为什么 processorid 都是 002

忽略其他问题,这是一个捕获和接近问题

你可以搜索一下,网上有很多关于它的文章,这正是 CLR 和 lambda 的工作方式

修复只是创建一个新的局部变量

for (int i = 0; i < n; ++i)
{
    var proc = new Processor(i);
    tasks.Add(new Task(() => proc.Process()));
    tasks[i].Start();
}

快速看一下,它似乎与变量作用域和将作用域折叠到 lambda 中有关。

试着改变你的循环,让它变成这样:

    for (int i = 0; i < n; ++i)
    {
        tasks.Add(new Task(() => new Processor(i).Process()));
        tasks[i].Start();
    }

另外,请问Processor是否真的需要class,难道不是一个简单的方法吗?您传入处理器的逻辑有些奇怪,但随后为每个循环迭代创建一个新处理器。你真的想要那个吗?