A word on async tasks, awaits, and deadlocks

To better explain what we did with the CreateUsers() method of the DbSeeder class, we should spend a few words about the concept async tasks.

Whoever knows the basics of thread programming within legacy ASP.NET knows well that you should never even think about blocking an async task. The reason isn't always immediate to explain and understand, yet we'll try to give it a shot. One of the first thing you should learn when working with sync methods invoking async tasks in ASP.NET is that when the top-level method awaits a task, its current execution context gets blocked until the task completes. This won't be a problem, unless that context allows only one thread to run at a time, which is precisely the case of the AspNetSynchronizationContext. If we combine these two things together, we can easily see that blocking an async method returning a task will expose our application to a high risk of deadlock. A deadlock, from a software development perspective, is a dreadful situation that occurs whenever a process or thread enters a waiting state indefinitely, usually because the resource it's waiting for is held by another waiting process. In any legacy ASP.NET web application, we'll face a deadlock every time we're blocking a task, simply because that task, in order to complete, will require the same execution context of the invoking method, which is kept blocked by that method until the task completes!

After hearing this terrifying story, there's definitely something that we should ask ourselves: why in the hell have we chosen to block the CreateUsers() method in the first place! Are we nuts or what?

As a matter of fact, we're not using legacy ASP.NET here; we're using .NET Core. Luckily enough, .NET Core dropped the former pattern based upon the SynchronizationContext for a contextless approach layered upon a versatile, deadlock-resilient thread pool. To keep it simple, we have nothing to worry about when using GetAwaiter().GetResult(), .Wait, .Result, or any other blocker; the only real downside in doing so is that we will lose all the benefits brought by asynchronous programming, such as performances and scalability. However, we can definitely live without them within the single request that will trigger the execution of our DbSeeder class in the whole application's lifetime.

For additional information regarding threads, async tasks, awaits, and asynchronous programming in ASP.NET we highly recommend that you check out the outstanding articles written by Stephen Cleary on the topic, which will greatly help you understand some of the most tricky and complex scenarios that can fall upon our heads when developing with these technologies. Some of them have been written a while ago, yet they never really age:

https://blogs.msdn.microsoft.com/pfxteam/2012/04/12/asyncawait-faq/.
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html.
https://msdn.microsoft.com/en-us/magazine/jj991977.aspx.
https://blog.stephencleary.com/2017/03/aspnetcore-synchronization-context.html.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.132.99