I am working on retrieving about 10 different types of data using http-requests with rather complex dependencies between them. And I am trying to find my way through this in an elegant, readable and maintainable way without waiting unnecessarily.
Let's assume, some method creates a Dictionary<string, Task<int>>. What is the most elegant way to convert this into Task<Dictionary<string, int>>?
The new outer Task should finish, as soon as all Tasks contained in the dictionary are finished.
Of course, I can write this manually:
Dictionary<string, Task<int>> values = GetValues();
Task<Dictionary<string, int>> result = Task.Run(async () => {
Dictionary<string, int> rewrapped = new();
foreach (var entry in values) {
rewrapped.Add(entry.Key, await entry.Value);
}
return rewrapped;
});
But isn't there a better way?
Rule of thumb: Never use Task.Run instead of it being truly async, it will use a thread to mimic asyncronity!
You just have to await the values, then get the Results:
Dictionary<string, Task<int>> values = GetValues();
await Task.WhenAll(values.Values);
Dictionary<string, int> results = values.ToDictionary(p => p.Key, p => p.Value.Result);
You can wrap the last two lines in a method, if you really want a Task<Dictionary<string, int>>.
async Task<Dictionary<string, int>> Unwrap(Dictionary<string, Task<int>> values)
{
await Task.WhenAll(values.Values);
return values.ToDictionary(p => p.Key, p => p.Value.Result);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With