I'm looking for a good way to run async methods in parallel, without having the burden of keeping my Task objects and getting their results from their task, because I feel this makes for less readable code.
I know I can run two async methods in parallel like this:
var t1 = RunAsync1();
var t2 = RunAsync2();
await Task.WhenAll(t1, t2)
var result1 = t1.Result;
var result2 = t2.Result;
For a website that makes a lot of API calls to external services that have nothing to do with each other, I was trying to make this more readable for my fellow developers and take away some of the burden of keeping the t1, t2, ... variables.
I came up with the following, but don't know if this is a good way to handle this. Are there downsides to passing my ModelClass to SetResultOfTask1 and SetResultOfTask2 methods, like possible memory leaks maybe or something else?
public async Task GetResult()
{
var model = new ModelClass();
await ExecuteInParallel(SetResultOfTask1(model), SetResultOfTask2(model));
//I can now proceed knowing that model.AsyncResult1 and model.AsyncResult2 should be filled in.
}
private async Task ExecuteInParallel(params Task[] tasks)
{
return Task.WhenAll(tasks);
}
private async Task SetResultOfTask1(ModelClass m)
{
m.AsyncResult1 = await GetAsync1();
}
private async Task SetResultOfTask2(ModelClass m)
{
m.AsyncResult2 = await GetAsync2();
}
Or is there perhaps a better way to handle this that keeps its readability? Thank you for your thoughts and advice!
UPDATE
A fair point was made that the method ExecuteInParallel doesn't have any value, so this can be removed for the sake of readability.
My idea was to avoid a method that looks like this :
public async Task<ModelClass> GetModel()
{
var t1 = RunAsync1();
var t2 = RunAsync2();
var t3 = GetProductTypesAsync();
var t4 = GetUserInformationAsync();
await Task.WhenAll(t1, t2, t3, t4);
var model = new ModelClass();
model.Type1 = t1.Result;
model.Type2 = t2.Result;
if (t3.Result == null) {
//do something else
}
foreach (var productType in t4.Result) {
//get some more information per product type
model.ProductTypes.Add(productType)
}
return model;
}
and replace it with a method that is more expressive in what is happening, like this. As an outside programmer, I can just read what's happening to construct the model.
public async Task<ModelClass> GetModel()
{
var model = new ModelClass();
//these four methods have nothing to do with one another, other than their end result must end up in my instance of ModelClass, which is why I got tempted into trying to execute this in parallel.
await GetGeneralInformationAboutTheProduct(model);
await LoadProductTypes(model);
await LoadUserInformation(model);
await LoadShoppingCartInformation(model);
return model;
}