Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async all the way down?

Trying to understand the new async/await pattern, I have one question which I can't find an answer to, namely if I should decorate my methods with async, if I intend to call those methods from other async functions, or just return Tasks where appropriate?

In other words, which of these classes A, B or C is best, and why?

class A<T>
{
      public async Task<T> foo1() //Should be consumed
      {
          return await foo2();
      }

      public async Task<T> foo2() //Could be consumed
      {
          return await foo3();
      }

      private async Task<T> foo3() //Private
      {
          return await Task.Run(...);
      }
}

class B<T>
{
      public async Task<T> foo1() //Should be consumed
      {
          return await foo2();
      }

      public async Task<T> foo2() //Could be consumed
      {
          return await foo3();
      }

      private Task<T> foo3() //Private
      {
          return Task.Run(...);
      }
}

class C<T>
{
      public async Task<T> foo1() //Should be consumed
      {
          return await foo2();
      }

      public Task<T> foo2() //Could be consumed
      {
          return foo3();
      }

      private Task<T> foo3() //Private
      {
          return Task.Run(...);
      }
}

It seems redundant to overdecorate methods so I naturally lean toward C, but at the same time it feels somewhat awkward to work with Task<T> unless you use the await keyword.

like image 714
Gleno Avatar asked Aug 18 '12 06:08

Gleno


People also ask

Does every async always return promise?

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.

Should I use async void?

To summarize this first guideline, you should prefer async Task to async void. Async Task methods enable easier error-handling, composability and testability. The exception to this guideline is asynchronous event handlers, which must return void.

Should all methods be async?

If a method has no async operations inside it there's no benefit in making it async . You should only have async methods where you have an async operation (I/O, DB, etc.). If your application has a lot of these I/O methods and they spread throughout your code base, that's not a bad thing.

What does async mean in Swift?

An asynchronous function in Swift can give up the thread that it's running on, which lets another asynchronous function run on that thread while the first function is blocked. When an asynchronous function resumes, Swift doesn't make any guarantee about which thread that function will run on.


1 Answers

Both versions work effectively the same, the only difference is that when you use await here, you get some performance penalty (because the state machine must be set up and a continuation will most likely be used).

So, it comes down to a tradeoff: Do you want your methods to be somewhat more efficient at the cost of being slightly less readable? Or are you willing to sacrifice performance for readability?

Usually, I would advise you to go for readability first and only focus on performance if profiling tells you it's worth it. But in this case, I think the increase in readability is small, so I would probably not use await.

Also note that your class C still doesn't go far enough: foo1() also doesn't need await.

like image 114
svick Avatar answered Oct 20 '22 21:10

svick