Don’t Block on Async Code in DotNet Framework
Let’s dive into our problem to see why we don’t block our sync code in dotNet, I use a simple example to demonstrate our problem.
This is an API controller name Test with simple action Get() let’s test our API
we using postman to test API no result coming, If we use the browser to test API we will see it load... without any result
Why no result because Deadlock, what Deadlock 😲, let’s see why deadlock happens.
Let’s debug and see what happens
First UI Thread(Asp.net request context) Call GetJsonAsync() Method and execute the first line Debug.Write(“Get Data”)
Second when see the await keyword the code after await executes in a separate thread and the control return to Get() Action.
Third executes the next line jsonTask.Result , .Result or .GetAwaiter().GetResult() or any kind of this will Block the main thread(UI thread) or calling thread, block UI thread means you can’t interact with the screen it is frozen you can’t scroll or do anything and wait when the code after await keyword is Finish.
now the code after await is finished and a separate thread that executes the code goes to SynchronizatonContext(responsible to manage Threads)
The conversation between WorkerThread and SynchronizatonContext
Worker Thread Say “Hi SynchronizatonContext I finished my work”
SynchronizationContext Reply “Great work, what is the thread calling you dear to continue the work”
worker Thread Reply “Main thread”
SynchronizationContext Reply “What, The main thread is blocked😰😰”
so now we wait for the main thread because it blocks and the deadlock happens so no result, and the browser load...
How to avoid deadlock ?
- In your “library” async methods, use ConfigureAwait(false) wherever possible.
- Don’t block on Tasks; use async all the way down.
when you make async method ConfigureAwait(false) The Worker Thread Tell SynchronizationContext ,you don’t need to make context switch I will execute the continuation Task, so you didn’t need The Main Thread
Where I using ConfigureAwait(false) ?
use configureAwait(false) in your ClassLibrary the shared code that will consume by the UI Layer and avoid using in UI Component
If you make ConfigureAwait false and the code after it need the UI Thread like the code in our example the textBox1.Text=jsonTask need UI Thead because textBox1,It will throw an exception.
Did I need ConfigureAwait(false) in .net core?
No, Because .net core didn’t using SynchronizationContext so you can using .Result or .GetAwaiter().GetResult() without fearing from deadlock but you didn’t benefit from Async/Await.but in some ClassLibrary that may consume by (.Net Framework or WindowsForm or WPF or any framework that may using SynchronizationContext) you need to added it.