gpt4 book ai didi

C# TaskFactory 未完成所有迭代

转载 作者:行者123 更新时间:2023-11-30 19:35:54 27 4
gpt4 key购买 nike

我在使用 TaskFactory 时遇到了一些奇怪的问题:

Task<int[]> parent = Task.Run(() =>
{
int length = 100;
var results = new int[length];
TaskFactory tf = new TaskFactory(TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously);

// Create a list of tasks that we can wait for
List<Task> taskList = new List<Task>();
for (int i = 0; i < length - 1; i++) // have to set -1 on length else out of bounds exception, huh?
{
taskList.Add(tf.StartNew(() => results[i] = i));
}
// Now wait for all tasks to complete
Task.WaitAll(taskList.ToArray());

return results;
});

parent.Wait();

var finalTask = parent.ContinueWith(
parentTask =>
{
foreach (int i in parentTask.Result)
{
Console.WriteLine(i);
}
});

finalTask.Wait();

Console.ReadKey();

这给出了类似的输出:

00004个5个0000100121314...099

我不明白为什么不是所有的索引都是非零的。

谢谢,

最佳答案

当您使用 lambda 捕获一个变量时,这个变量被放入一个编译器生成的对象中,该对象在内部和外部范围之间共享。当您这样做时:

for (int i = 0; i < length - 1; i++)
{
taskList.Add(tf.StartNew(() => results[i] = i));
}

变量 i 在循环和所有子任务之间共享。只有一个 i,它在任务运行时被循环修改。这是一种竞争条件,每次都会在数组中产生看似随机的数据,具体取决于任务的安排方式。

解决这个问题的最简单方法是创建一个作用域为循环体的不可变变量:

for (int i = 0; i < length; i++) // You can now use length instead of length - 1
{
int innerI = i;
taskList.Add(tf.StartNew(() => results[innerI] = innerI));
}

现在每个任务都有一个单独的 innerI 变量,并且它被赋值 i 恰好一次并且不会改变。


想象一下编译器将旧代码转换成

class Generated1
{
public int i;
}
var context = new Generated1(); // Exactly one copy of i
for (context.i = 0; context.i < length - 1; context.i++)
{
taskList.Add(tf.StartNew(() => results[context.i] = context.i));
}

编译器转换后的新代码变成了

class Generated2
{
public int innerI;
}
for (int i = 0; i < length - 1; i++)
{
var context = new Generated2(); // New copy of innerI for every loop iteration
context.innerI = i;
taskList.Add(tf.StartNew(() => results[context.innerI] = context.innerI));
}

关于为什么必须使用 length - 1:您的一些任务直到循环完成后才运行。那时,i == length,因此当您尝试使用 i 作为数组的索引时,您会得到一个 IndexOutOfRangeException。当您使用 i 修复竞争条件时,这种情况就不会再发生了。

关于C# TaskFactory 未完成所有迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50240874/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com