Awaiting multiple Tasks with different results

后端 未结 10 1381
醉话见心
醉话见心 2020-11-22 12:59

I have 3 tasks:

private async Task FeedCat() {}
private async Task SellHouse() {}
private async Task BuyCar() {}
         


        
10条回答
  •  伪装坚强ぢ
    2020-11-22 13:18

    Forward Warning

    Just a quick headsup to those visiting this and other similar threads looking for a way to parallelize EntityFramework using async+await+task tool-set: The pattern shown here is sound, however, when it comes to the special snowflake of EF you will not achieve parallel execution unless and until you use a separate (new) db-context-instance inside each and every *Async() call involved.

    This sort of thing is necessary due to inherent design limitations of ef-db-contexts which forbid running multiple queries in parallel in the same ef-db-context instance.


    Capitalizing on the answers already given, this is the way to make sure that you collect all values even in the case that one or more of the tasks results in an exception:

      public async Task Foobar() {
        async Task Awaited(Task a, Task b, Task c) {
            return DoSomething(await a, await b, await c);
        }
    
        using (var carTask = BuyCarAsync())
        using (var catTask = FeedCatAsync())
        using (var houseTask = SellHouseAsync())
        {
            if (carTask.Status == TaskStatus.RanToCompletion //triple
                && catTask.Status == TaskStatus.RanToCompletion //cache
                && houseTask.Status == TaskStatus.RanToCompletion) { //hits
                return Task.FromResult(DoSomething(catTask.Result, carTask.Result, houseTask.Result)); //fast-track
            }
    
            cat = await catTask;
            car = await carTask;
            house = await houseTask;
            //or Task.AwaitAll(carTask, catTask, houseTask);
            //or await Task.WhenAll(carTask, catTask, houseTask);
            //it depends on how you like exception handling better
    
            return Awaited(catTask, carTask, houseTask);
       }
     }
    

    An alternative implementation that has more or less the same performance characteristics could be:

     public async Task Foobar() {
        using (var carTask = BuyCarAsync())
        using (var catTask = FeedCatAsync())
        using (var houseTask = SellHouseAsync())
        {
            cat = catTask.Status == TaskStatus.RanToCompletion ? catTask.Result : (await catTask);
            car = carTask.Status == TaskStatus.RanToCompletion ? carTask.Result : (await carTask);
            house = houseTask.Status == TaskStatus.RanToCompletion ? houseTask.Result : (await houseTask);
    
            return DoSomething(cat, car, house);
         }
     }
    

提交回复
热议问题