简体   繁体   中英

Find Result of Parallel Async Tasks

Based off this question I'm trying to set up code to save several images to Azure Blob Storage in parallel. This method below works fine and awaiting Task.WhenAll(tasks) awaits for all to complete before continuing.

The only trouble is, I would like to be able to find out if each request to store the information in our database actually succeeded. _db.AddImageAsync returns a bool and the code below waits for all tasks to complete but when I check the result of all the tasks each is false (even if I actually returned true inside the brackets).

Each task in the Enumerable says the result has not yet been computed even though I stepped through with breakpoints and each has been carried out.

  var tasks = wantedSizes.Select(async (wantedSize, index) =>
  {
    var resize = size.CalculateResize(wantedSize.GetMaxSize());
    var quality = wantedSize.GetQuality();

    using (var output = ImageProcessHelper.Process(streams[index], resize, quality))
    {
        var path = await AzureBlobHelper.SaveFileAsync(output, FileType.Image);
        var result = await _db.AddImageAsync(id, wantedSize, imageNumber, path);
        return result;
    }
  });

  await Task.WhenAll(tasks)

  if (!tasks.All(task => task.Result))
      return new ApiResponse(ResponseStatus.Fail);

Any help is much appreciated!

Because .Select( is lazy evaluated and returns a IEnumerable<Task<bool>> you are causing the .Select( to be run multiple times when you iterate over the result multiple times. Throw a .ToList() on it to make it a List<Task<bool>> and that will only execute the .Select( once and the multiple enumerations will be over the returned List<Task<bool>> which will not have side effects.

  var tasks = wantedSizes.Select(async (wantedSize, index) =>
  {
    var resize = size.CalculateResize(wantedSize.GetMaxSize());
    var quality = wantedSize.GetQuality();

    using (var output = ImageProcessHelper.Process(streams[index], resize, quality))
    {
        var path = await AzureBlobHelper.SaveFileAsync(output, FileType.Image);
        //Double check your documentation, is _db.AddImageAsync thread safe?
        var result = await _db.AddImageAsync(id, wantedSize, imageNumber, path);
        return result;
    }
  }).ToList(); //We run the Select once here to process the .ToList().

  await Task.WhenAll(tasks) //This is the first enumeration of the variable "tasks".

  if (!tasks.All(task => task.Result)) //This is a 2nd enumeration of the variable.
      return new ApiResponse(ResponseStatus.Fail);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM