Async / await WhenAll by two methods with the same return type
I am trying to upload files asynchronously to an S3 bucket. I can do this successfully with the following code.
I cannot figure out how to handle two different methods that have the same return type at the same time.
UploadImages
and UploadAttachments
both return IEnumerable
of EntityUploadResult
. How do I execute them in Parallel and return the results after they are completed?
public async Task<List<EntityUploadResult>> BulkUploadFiles(IEnumerable<BulkUploadFile> files)
{
var results = new List<EntityUploadResult>();
var images = UploadImages(files.Where(x => x.FileType == BulkFileType.Image).AsEnumerable());
var attachments = UploadAttachments(files.Where(x => x.FileType == BulkFileType.Attachment).AsEnumerable());
results.AddRange(await images);
results.AddRange(await attachments);
return results;
}
private async Task<IEnumerable<EntityUploadResult>> UploadImages(IEnumerable<BulkUploadFile> files)
{
return await Task.WhenAll(files.Select(i => UploadImage(i)));
}
private async Task<IEnumerable<EntityUploadResult>> UploadAttachments(IEnumerable<BulkUploadFile> files)
{
return await Task.WhenAll(files.Select(i => UploadAttachment(i)));
}
source to share
First of all, this is what you are already doing by running both operations and only then waiting for them.
But if you want to do it with Task.WhenAll
and only wait once, you can use the return value, which is the collection of all the return values of the operations, and combine them withSelectMany
public async Task<List<EntityUploadResult>> BulkUploadFiles(IEnumerable<BulkUploadFile> files)
{
var images = UploadImages(files.Where(x => x.FileType == BulkFileType.Image).AsEnumerable());
var attachments = UploadAttachments(files.Where(x => x.FileType == BulkFileType.Attachment).AsEnumerable());
var results = await Task.WhenAll(images, attachments);
return results.SelectMany(_ => _).ToList();
}
source to share
await
to a WhenAll
with both of them, then review Result
later or if (as in this case) through the returned result WhenAll
:
If the two types are different, you can do so (also an option if the types are the same);
await Task.WhenAll(images, attachments);
var imgResult = images.Result;
var attResult = attachments.Result;
If they are of the same type, you can also do:
IEnumerable<IEnumerable<EntityUploadResult>> = await Task.WhenAll(images, attachments);
As such your lines:
results.AddRange(await images);
results.AddRange(await attachments);
May be replaced by:
results.AddRange((await Task.WhenAll(images, attachments)).SelectMany(u => u));
source to share