DEV Community

Cover image for Await Tuples Directly
Mehran Davoudi
Mehran Davoudi

Posted on

Await Tuples Directly

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());
Enter fullscreen mode Exit fullscreen mode

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();
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
msynk profile image
Saleh Yusefnejad

oh nice one👌

Collapse
 
thomasouvre profile image
ouvré thomas

Could be dangerous with non thread safe API (like EF dbcontext)