Max*_*Max 6 c# lambda asynchronous
我试图同时运行几个任务,我遇到了一个似乎无法理解或解决的问题.
我以前有这样的功能:
private void async DoThings(int index, bool b) {
await SomeAsynchronousTasks();
var item = items[index];
item.DoSomeProcessing();
if(b)
AVolatileList[index] = item; //volatile or not, it does not work
else
AnotherVolatileList[index] = item;
}
Run Code Online (Sandbox Code Playgroud)
我想用for循环调用Task.Run().但是我找不到向这个发送参数的方法,Action<int, bool>并且每个人都建议在类似的情况下使用lambdas:
for(int index = 0; index < MAX; index++) { //let's say that MAX equals 400
bool b = CheckSomething();
Task.Run(async () => {
await SomeAsynchronousTasks();
var item = items[index]; //here, index is always evaluated at 400
item.DoSomeProcessing();
if(b)
AVolatileList[index] = item; //volatile or not, it does not work
else
AnotherVolatileList[index] = item;
}
}
Run Code Online (Sandbox Code Playgroud)
我认为在lambdas中使用局部变量会"捕获"它们的值,但它看起来却没有; 它将始终采用索引的值,就好像在for循环结束时捕获该值一样.该index变量在400中在每个迭代拉姆达评价所以当然我得到一个IndexOutOfRangeException400倍(items.Count实际上是MAX).
我真的不确定这里发生了什么(虽然我真的很好奇)但我不知道如何做我想要实现的目标.任何提示都是受欢迎的!
制作索引变量的本地副本:
for(int index = 0; index < MAX; index++) {
var localIndex = index;
Task.Run(async () => {
await SomeAsynchronousTasks();
var item = items[index];
item.DoSomeProcessing();
if(b)
AVolatileList[index] = item;
else
AnotherVolatileList[index] = item;
}
}
Run Code Online (Sandbox Code Playgroud)
这是由于C#for循环的方式:只有一个index变量更新,所有lambdas都捕获相同的变量(使用lambdas,捕获变量,而不是值).
作为旁注,我建议你:
async void.您永远不知道async void方法何时完成,并且它们具有困难的错误处理语义.await所有的异步操作.即,不要忽略从中返回的任务Task.Run.使用Task.WhenAll等等await.这允许异常传播.例如,这是一种使用方法WhenAll:
var tasks = Enumerable.Range(0, MAX).Select(index =>
Task.Run(async () => {
await SomeAsynchronousTasks();
var item = items[localIndex];
item.DoSomeProcessing();
if(b)
AVolatileList[localIndex] = item;
else
AnotherVolatileList[localIndex] = item;
}));
await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
542 次 |
| 最近记录: |