Waiting for Task.WhenAll vs..select (async .. => await)

just a quick question. We have some misunderstanding here.

we have:

var tasks = files.Select(async fileName => await IngestFileAsync(container, fileName)); var results = await Task.WhenAll(tasks); 

I say that the first line still goes in parallel, but my colleague says differently. In addition, he says that the second await does not make sense, because all the actions have already been completed.

is the same code:

 var tasks = files.Select(fileName => IngestFileAsync(container, fileName)); var results = await Task.WhenAll(tasks); 

as:

 var tasks = files.Select(async fileName => await IngestFileAsync(container, fileName)); var results = Task.WhenAll(tasks); 

Can anyone shed some light on this?

greetings.

Added: oke, so it will work at the same time.

However, someone can add additional information about what is the difference between these code snippets: https://dotnetfiddle.net/lzv2B7 https://dotnetfiddle.net/dMusus

(notification line 16, async and await ). Is there any difference between these 2? I would expect that with async and wait for it to start directly, but without it it will start when it comes to Await Task.WhenAll(tasks);

added for clarity - this is my code -:

  private async Task<Result> IngestFilesAsync(ICloudBlobContainer container, IEnumerable<string> files) { _logger.LogDebug("Start IngestFilesAsync"); var tasks = files.Select(fileName => IngestFileAsync(container, fileName)); var results = await Task.WhenAll(tasks); _logger.LogDebug("All tasks completed"); if (results.Any(t => t.IsFailure)) { return Result.Fail(string.Join(",", results.Select(f => f.Error))); } return Result.Ok(); } private async Task<Result> IngestFileAsync(ICloudBlobContainer container, string fileName) { _logger.LogDebug("Start IngestFileAsync"); var blob = container.GetBlockBlobReference(fileName); _logger.LogDebug("Blob retrieved"); if (await blob.ExistsAsync()) { using (var memoryStream = new MemoryStream()) { _logger.LogDebug("Start download to stream"); await blob.DownloadToStreamAsync(memoryStream); _logger.LogDebug("To mem downloaded"); _logger.LogDebug("Start ftp-upload"); return await _targetFTP.UploadAsync(memoryStream, fileName); } } _logger.LogWarning("Blob does not exists"); return Result.Fail($"Blob '{fileName}' does not exist"); } 

where _targetFTP.UploadAsync(memoryStream, fileName); task again, etc. etc.

+7
c # asynchronous
source share
1 answer

async x => await f() creates an anonymous function that returns a task. This task effectively completes the creation created with f : it will be completed immediately afterwards. In particular, this anonymous function returns an unfinished task as soon as possible.

.Select does not behave differently depending on whether the enumeration type is one of the tasks. This allows you to get the next result directly when the first returned task is still running.

Code fragments are not 100% identical, but the difference you are asking for does not exist.

The differences are small; the most noticeable change is probably due to exception handling. Suppose you have two functions not yet implemented:

 Task Sync() => throw new NotImplementedException(); async Task Async() => throw new NotImplementedException(); 

Here var task = Sync(); obviously does not work right away. But var task = Async(); different: it succeeds. The async causes a task to be created that catches the exception that has occurred.

The same difference also applies to .Select(x => Sync()) vs .Select(async x => await Sync()) .

+9
source share

All Articles