[英]C# Task.run(), passing parameter to
请考虑以下代码
attempt = 0;
for (int counter = 0; counter < 8; counter++)
{
if (attempt < totalitems)
{
Tasklist<output>.Add(Task.Run(() =>
{
return someasynctask(inputList[attempt]);
}));
}
else
{
break;
}
attempt++;
}
await Task.WhenAll(Tasklist).ConfigureAwait(false);
我希望有8个并发任务,每个任务同时处理不同的输入,最后检查结果,当它们全部完成时。 因为我没有等待Task.Run()的完成尝试在任务开始之前增加,并且当任务开始时,输入列表中可能存在未处理或处理两次或更多次的项目(由于不确定性)在尝试价值。
怎么做?
问题在于使用“lambda”:当Task.Run(() => return someasynctask(inputList[attempt]));
在执行期间到达,变量attempt
被捕获,而不是它的值(即它是“闭包”)。 因此,当执行lambda时,将使用该特定时刻的变量值。
只需在lambda之前添加变量的临时副本,然后使用它。 例如
if (attempt < totalitems)
{
int localAttempt = attempt;
Tasklist<output>.Add(Task.Run(() =>
{
return someasynctask(inputList[localAttempt]);
}));
}
感谢@gobes的回答:
尝试这个:
attempt = 0;
for (int counter = 0; counter < 8; counter++)
{
if (attempt < totalitems)
{
Tasklist<output>.Add(Task.Run(() =>
{
int tmpAttempt = attempt;
return someasynctask(inputList[tmpAttempt]);
}));
}
else
{
break;
}
attempt++;
}
await Task.WhenAll(Tasklist).ConfigureAwait(false);
实际上,编译器正在做的是将lambda提取到一个方法中,该方法位于一个自动生成的类中,该类引用了try变量。 这一点非常重要:生成的代码只引用另一个类的变量; 它没有复制它。 因此,方法可以看到每次尝试的变化。
执行过程中发生的事情大致如下:
用try = 0进入循环向你的任务列表添加一个类似lambda的方法的调用增加尝试重复循环之后,你有一些方法调用等待(没有双关语意图)执行,但是每个方法调用引用相同的变量因此,分享它的价值 - 最后影响它。
有关更多详细信息,我真的建议深入阅读C#,或者同类书籍 - 关于C#在Web上关闭的资源很多:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.