Parameters in asynchronous lambdas

后端 未结 2 544
清歌不尽
清歌不尽 2021-01-12 19:41

I am trying to run several tasks at the same time and I came across an issue I can\'t seem to be able to understand nor solve.

I used to have a function like this :<

2条回答
  •  一向
    一向 (楼主)
    2021-01-12 20:19

    Make a local copy of your index variable:

    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;
      }
    }
    

    This is due to the way C# does a for loop: there is only one index variable that is updated, and all your lambdas are capturing that same variable (with lambdas, variables are captured, not values).

    As a side note, I recommend that you:

    1. Avoid async void. You can never know when an async void method completes, and they have difficult error handling semantics.
    2. await all of your asynchronous operations. I.e., don't ignore the task returned from Task.Run. Use Task.WhenAll or the like to await for them. This allows exceptions to propagate.

    For example, here's one way to use 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);
    

提交回复
热议问题