Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Struggling with async/await C# [closed]

I read alot about async/await, but I still have some lack in understanding the following situation.

My question is, should I implement my "wrapper" methods as in DoSomething() or like in DoSomethingAsync().

So what's better (and why): Do I use await in wrapper methods or return the Task directly?

        public static async void Main()
        {
            await DoSomething();
            await DoSomethingAsync();
        }

        private static Task DoSomething()
        {
            return MyLibrary.DoSomethingAsync();
        }

        private static async Task DoSomethingAsync()
        {
            await MyLibrary.DoSomethingAsync().ConfigureAwait(false);
        }

        public class MyLibrary
        {
            public static async Task DoSomethingAsync()
            {
                // Here is some I/O
            }
        }
like image 974
coalmee Avatar asked Feb 16 '16 13:02

coalmee


People also ask

Is it OK to not await async?

If you forget to use await while calling an async function, the function starts executing. This means that await is not required for executing the function. The async function will return a promise, which you can use later.

Does await Block C#?

The await operator doesn't block the thread that evaluates the async method. When the await operator suspends the enclosing async method, the control returns to the caller of the method.

How can we avoid deadlock in async await?

You can use the following simple workaround in the scenario where you want to call an async method from a sync method: Before the call, clear the SynchronizationContext. Do the call, there will be no more deadlock here, wait for it to finish. Restore the SynchronizationContext.


1 Answers

Async/Await are still relatively new, but there are some good practices to help clarify an API. The basics are this:

  • A method declaring itself as async means it is expecting to await later on
  • async implicitly creates a Task for you.
  • await is like a bookmark. The application resumes where the await keyword was used.
  • You cannot await anything that is not IAwaitable (most commonly a Task) (citation)

In an application where there are both asynchronous calls and synchronous calls, we've adopted a naming convention:

  • async calls return Task or Task<T> and append the word Async to the end of the name.
  • Synchronous calls (the default) simply work like any method does and there is no special convention.

Often, there can be two methods which do the same thing, but one is synchronous and the other not. You can either implement it two different ways, or you can wrap one with the other. It really depends on your needs and what is going to give you the more responsive application.

In the example above, the proper way to handle async and normal method calls would be for MyLibrary to expose two methods. The example would be like this:

 public static class MyLibrary
 {
     public static void DoSomething()
     {
         // do some work
     }

     public static async Task DoSomethingAsync()
     {
         // do similar work but use async API,
         // can also simply call DoSomething().
     }
 }

 // In another part of code would be called like this:
 public static async Task BiggerMethod()
 {
     MyLibrary.DoSomething();
     await MyLibrary.DoSomethingAsync();
 }

What you want to avoid is wrapping an async method with a regular method. As soon as you work with the Task directly, you lose all benefits of async and await and you introduce places where your code can deadlock.

like image 79
Berin Loritsch Avatar answered Oct 09 '22 05:10

Berin Loritsch