Imagine if you could write code like this:
var task1 = CountAsync();
var task2 = GetMessageAsync();
// How to await tuples directly!?
var (count, message) = await (task1, task2);
// or even this:
var (count, message) = await (CountAsync(), GetMsgAsync());
This would allow you to await multiple asynchronous tasks in a single line of code, without using Task.WhenAll
or Task.WhenAny
. How cool is that?
Unfortunately, this is not possible in C# as it is. A Tuple
is not an awaitable type, and you cannot use the await
keyword on it. Does that mean we have to give up on this idea? NO!
We can make it happen by using the power of extension methods.
You may already know that in C#, you can await any object that has a GetAwaiter
method that returns a TaskAwaiter
. This means that we can add an extension method called GetAwaiter
to tuples and make them awaitable.
public static TaskAwaiter<(T1, T2)> GetAwaiter<T1, T2>(this (Task<T1>, Task<T2>) tuple)
{
async Task<(T1, T2)> UnifyTasks()
{
var (task1, task2) = tuple;
await Task.WhenAll(task1, task2);
return (task1.Result, task2.Result);
}
return UnifyTasks().GetAwaiter();
}
That's it, all done!
Now you can easily await on tuples. To make it available on all types of tuples and enumerables, I've written this library on GitHub.
All you need is to install EasyAsync Nuget package:
Install-Package EasyAsync
Top comments (2)
oh nice one👌
Could be dangerous with non thread safe API (like EF dbcontext)