C# Asynchronous Programming Full Tutorial : Async / Await / Task and Deadlock Fix by ConfigureAwait #319
FurkanGozukara
announced in
Tutorials
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
C# Asynchronous Programming Full Tutorial : Async / Await / Task and Deadlock Fix by ConfigureAwait
Full tutorial: https://www.youtube.com/watch?v=I4cnX_odC1M
In this lecture video, I am going to explain #asynchronous #programming concepts when using .NET Core 7 with C# #programming language. I will code a #WPF application to demonstrate #Async, #Await, #ConfigureAwait, and #Task concepts while doing asynchronous coding. I will show how ConfigureAwait is important to prevent deadlocks while using "async" and "await" keywords.
The code repository of this lecture :
https://github.com/FurkanGozukara/C-Async-Await-Task-Deadlock-Fix-by-ConfigureAwait-Full-Tutorial-Asynchronous-Programming
Moreover, we cover the following #howto topics:
How to do asynchronous programming with C# and .NET
How to use Async, Await and ConfigureAwait
How to use Task, Task.Wait and ContinueWith
How to utilize Dispatcher.BeginInvoke to update UI elements from different tasks, sub-tasks, threads
How to utilize Thread.CurrentThread.ManagedThreadId to see which code is executed in which thread
How to download source of a web page / URL asynchronously and properly with using HttpClient and Content.ReadAsStringAsync
00:00:00 Introduction Task, Async, Await and composing the demo application
00:02:18 Generating Async deadlock causing example
00:08:03 How to see thread IDs during the runtime
00:11:47 How to fix deadlock
00:13:50 How to use ConfigureAwait properly
00:14:48 How to make UI responsive with proper Async Await usage
00:17:09 How to make async but main thread blocking code with TaskFactory.StartNew and Task.Wait
00:20:52 How to make fully asynchronous and non-blocking UI with TaskFactory and ContinueWith
00:23:36 How to update UI thread from sub-thread with Dispatcher
We have manually corrected the subtitles for the video so watch the tutorial with subtitles on if you have a hard time understand
Please join Our Discord server for asking questions and have discussions: https://discord.gg/rfttctFewW
Please follow us on Twitter: https://twitter.com/SECourses
Please follow us on Facebook: https://www.facebook.com/OfficialSECourses
If you are interested in programming our playlists will teach you how to program and code from scratch: https://www.youtube.com/c/SECourses/playlists
[1] Introduction to Programming Full Course with C# playlist
[2] Advanced Programming with C# Full Course Playlist
[3] Object Oriented Programming Full Course with C# playlist
[4] Asp #NETCore V5 - MVC Pattern - Bootstrap V5 - Responsive Web Programming with C# Full Course Playlist
[5] Artificial Intelligence (AI) and Machine Learning (ML) Full Course with C# Examples playlist
[6] Software Engineering Full Course playlist
[7] Security of Information Systems Full Course playlist
Thumbnail: Freepik (@fullvector) - Data processing, software program development, code review, database concept. #dotnet #dotnet7 #csharp
Video Transcription
00:00:00 Hello everyone. I am Dr. Furkan Gözükara. In this lecture video, I am going to explain asynchronous
00:00:07 programming concepts when using .NET Core 7 with C-Sharp programming language. I will code a WPF
00:00:14 application to demonstrate async, await, configure await and task concepts while doing asynchronous
00:00:21 coding. I will show how ConfigureAwait is important to prevent deadlocks while using
00:00:27 async and await keywords. Let's start coding with composing a .NET Core 7 WPF application.
00:00:33 If your Visual Studio is lacking .NET Core 7, just download latest Visual Studio Community
00:00:39 Edition and update it to the latest version. Here let me show you how to update your Visual Studio.
00:01:01 As you can see, my Visual Studio is up to date. Its version is 17.4.1. Okay,
00:01:08 so let's start composing our WPF project. I am going to pick WPF application. You
00:01:15 can also look for it with searching WPF. And then you see there is ASP.NET Core WPF app.
00:01:24 Then click next. Okay, it will be in my desktop. Let's say
00:01:32 async programming. I am going to pick .NET 7 and this is .NET Core web app. Let's fix
00:01:41 it quickly. Okay, here WPF application and it is with .NET Core. Okay, next.
00:01:53 You see it says that there is WPF application. Okay .NET Core 7.
00:02:06 Okay, application is started now. The interface is loaded. So let's start
00:02:14 with generating a button control. First I will show you how a deadlock can happen when we are
00:02:23 doing asynchronous programming with async and await keywords. Let's say test async deadlock.
00:02:42 Okay and with double clicking it I am going to compose click event here.
00:02:49 Okay, so let's assume that we have an async method that will return a string.
00:02:57 Let's say return source code of a web page as a string. Okay.
00:03:18 I will use HTTP client.
00:03:24 Okay and inside here we will use.
00:03:34 We will use HTTP response.
00:03:40 Okay. Sorry not not necessarily we need that.
00:03:56 You see it has suggested me to auto complete is like this and it's correct. And we will return.
00:04:09 Response request. Content. Okay, then let's see. Okay, like this.
00:04:24 All right. However, since this is asynchronous with async keyword. We need to say await here.
00:04:34 And since this is an async method, we can't just return it like this. We have to return a task
00:04:43 like this. Okay. And let's add a label or a text
00:04:49 block to display source code. I'm going to pick a text block.
00:04:57 Okay, let's name it as block source code.
00:05:05 Okay, I have named it as txt block source code.
00:05:10 Then let's assign text of txt block source code equal to return source code of
00:05:21 my developed web game web based game, which is HTTPS www monsters MMORPG.com. Okay.
00:05:33 However, to access result of async method, we have to get result. So what does this async do?
00:05:45 Async means that that method is asynchronous and it will not block the thread that it is executed.
00:05:58 However, to get its result, I need to use await keyword.
00:06:04 And when you use await keyword, then you don't need to access it by result.
00:06:12 So when I run this code, what will happen? Let's see. Let's run and run our application and see.
00:06:26 Okay, I am clicking it and you see it has returned the result as expected. Because because there is a
00:06:39 key issue here, you see my button click is now also asynchronous. However, if I don't want to
00:06:48 make it asynchronous, then I need to return async keyword here that the Visual Studio
00:06:54 did put automatically and I need to use result like this. Okay, let's see now what happens.
00:07:06 Okay, I'm clicking and my application is completely frozen. Do you know why?
00:07:13 Because currently the UI thread is blocked. The reason is that UI
00:07:20 thread is waiting to waiting the result of this method call and this method call
00:07:28 is not able to execute because the UI thread is already frozen. So how can I solve this problem?
00:07:40 So for solving this problem, I can use configure await. So when you set configure await false
00:07:49 on an async method, this means that this method can now run on a different thread.
00:07:59 Okay, so to see the thread IDs that each method is running, let's use managed thread ID code.
00:08:11 Okay, let's write it to our output window with thread.
00:08:23 Okay, current thread manage thread ID. Okay, so it says that thread is
00:08:27 not existing in the current context for that I am adding using threads.
00:08:34 Okay, so this will print the thread ID of the thread that this line is executed. Then let's
00:08:42 also see the thread ID here. Let's also add some extra information as the inside
00:08:54 here. Then let's also write it as like this inside here. And then one second.
00:09:08 Okay, inside the first using statement inside using HTTP client and inside here. Okay, so
00:09:28 first, let's run it without configure, await and see which output we are getting.
00:09:40 Okay, let's check out the output window. So, okay, we see that inside btnTestAsyncDeadLock_Click,
00:09:51 which is here, the thread ID is one. It is expected because we are currently inside
00:09:58 the main UI thread, and it is one and in the source code. So it has entered here, we are
00:10:06 still inside thread ID one. And then we have entered here as well inside using HTTP client.
00:10:16 However, since we are doing await here, now it becomes asynchronous call and it
00:10:27 locks our execution. And you see we didn't enter inside here because the UI thread is
00:10:37 now awaiting that response. So the main thread is UI thread is locked, frozen.
00:10:46 And this execution is waiting that thread to be released. Okay, so when I add this execution,
00:11:00 configure await as false. Now let's see how to output. Let's see the output again.
00:11:11 Okay, the button is still frozen because it is not anymore asynchronous. However, now we can
00:11:17 see inside using response. You see inside here now running in a different thread and the thread ID is
00:11:24 six. Okay, so this is where configure await is very useful because when you set ConfigureAwait
00:11:36 false, then that asynchronous method call becomes, starts running in a different thread. Okay,
00:11:48 so if we don't want the interface to be frozen, let's copy and paste this button.
00:11:54 And let's say btn test proper async code. Okay, proper async code.
00:12:05 Okay, so this will cause a deadlock, so I'm going to delete this.
00:12:13 All right. Oh, we don't need that actually. So this is return source code with
00:12:23 or let's say let's add an option here. Bool cause deadlock equal to false. Okay.
00:12:37 Okay, so if you don't want to cause deadlock, then configure await. Then I need to
00:12:46 give opposite of this. So by default it will cause a deadlock and to cause a deadlock. We need
00:12:54 to give configure await true. Okay. Maybe this make make you confused. So let's say bl configure
00:13:06 await by default. Let's make it false so it won't cause a deadlock.
00:13:13 Okay, now it won't cause a deadlock. So to cause a deadlock, I need to provide it true. Okay. Yes,
00:13:25 now it will cause a deadlock. Let's try. Okay, so you see we are never getting inside here.
00:13:36 So now it is deadlocked because main thread the UI thread is awaiting the result and the result
00:13:45 is awaiting main thread UI thread to be released to run. Okay, so each one is awaiting each one
00:13:54 and it causes a deadlock. All right, so let's make this as none that's locking or let's say
00:14:07 configure await asynchronous code. Okay, I need to change its click event. We can
00:14:18 configure await async code. Okay. This time we are just going to run it with false and let's try.
00:14:36 Okay, still, the interface is frozen during the runtime because this button click is not
00:14:42 asynchronous. However, it is not that locked. Okay. And let's also add another button, which
00:14:52 will be responsive. We can responsive. Okay, async click. Let's say it as responsive async click.
00:15:08 Okay, and I need to generate a new click event. Okay, so I'm going to mark this method as async
00:15:20 and I can also let Visual Studio to mark it as async automatically with await.
00:15:30 Okay, now you see it is automatically marked as async. Okay,
00:15:38 now in this case, it will not freeze the interface. Let's try. Okay, let's try again.
00:15:49 Okay, the interface is not freezing. However, meanwhile, the text block is getting updated.
00:15:56 During that time, the interface will freeze, of course, because it is getting updated.
00:16:02 And since source code is pretty big, it is not displayed entirely here.
00:16:09 It takes some time. Actually, maybe we can fix it with. Okay. I don't know. Let's see.
00:16:19 Max with max height, for example, let's say 6000 and let's see what happens.
00:16:28 Okay, probably we need to add scroll bars. Let's see horizontal alignment. No scroll,
00:16:37 scroll bar. Okay, scroll. No. Okay, anyway, it is not important for this lecture. And there is one
00:16:48 another methodology, one more method, actually two more methodology. So let's also see them.
00:16:54 I'm going to expand this a little bit more. Why? Okay,
00:17:07 here. Okay. Now I will use task methodology. Okay, so btnTaskExample.
00:17:17 I will call this as task version one. Okay, and let's generate this click event. So this time I
00:17:28 will start this code inside or let's say as a task task. Let's say var task = Task.Factory.StartNew.
00:17:42 Okay. It automatically completes. Very nice. And let's call it like this.
00:17:50 And by the way, still this is a async method. So I need to call await.
00:17:59 And I need to assign this into a string variable. Let's say string source.
00:18:10 Like this. And let's say the source is equal to await.result. Okay. Okay.
00:18:24 I need to provide the source code, of course. I mean the URL. All right. And no result. Okay.
00:18:34 And then what do I need to do is. I can do task.wait. This will make it synchronous.
00:18:45 And then I can assign the source like this. Okay. It says that this can be null here. So
00:18:57 let's initialize it like this. All right. You see, it is still pretty responsive.
00:19:08 But we never get the result. So in this case. We need to set configure await true.
00:19:20 Otherwise it will return from that asynchronous and the task wait will never work. I suppose.
00:19:28 Let's try. Yes, we did enter inside the request. Okay. All right. This is the sound of my girl.
00:19:42 Okay, we do. We do enter inside the request. However, it is obvious that the source code
00:19:52 is immediately executed without waiting. So the task is completed immediately. Since we
00:20:00 are doing an asynchronous call here. And therefore, maybe we need to do. Let's see.
00:20:11 Okay, we need to turn this asynchronous call into a synchronous call because we are already spawning
00:20:18 a new task. And here we just need to provide or let's say, get result. Okay. And we need to
00:20:28 remove the wait keyword. All right. Now, since this will run inside a different thread than the
00:20:37 main thread, then it won't cause any problem as a deadlock. However, our interface will be still
00:20:46 frozen. Let's try. Okay. It is working. Now let's make another example of task with ContinueWith. So
00:20:58 I will call this task as version two. Okay. And let's say btn task version two. All right.
00:21:11 Okay. Okay. So in this case, we are going to use a different methodology as
00:21:23 continue with. All right. And it says we need a new action. Okay. Action. Okay. And. It says task.
00:21:43 Okay, one moment. It is pretty simple, actually. So we are going to call this T1 parameter,
00:21:53 which will be when we hover it, we see that it is task T1. So this means that it is the result
00:21:59 of execution of this task. Okay. And inside that we will have the result of the task. Therefore,
00:22:10 I will assign. I don't need this anymore. The text as equal to Ok.
00:22:21 T1. Okay. Result. Okay. And I just need to return the result of the inner execution. Okay.
00:22:35 Now this is supposed to not block anything and update the text block. Let's try. Okay.
00:22:41 It is not block it. Okay. Inside is called. All right. So we have a little bit. Another problem.
00:22:51 Okay. Which is this is task return. Okay. We are waiting it. We are locking it.
00:22:59 So let's try. Maybe we didn't wait. Okay. We did enter inside. Oh, we have a system invalid
00:23:08 operation exception somewhere. Okay. Let's put a break point here. Maybe our error is there.
00:23:17 Okay. And. When we debug the result. Okay. The result is there as well. Oh, I know the reason.
00:23:26 I know the problem. The problem is we cannot update the UI element inside another task. So
00:23:37 I need to do use dispatcher. Let's say begin invoke new action.
00:23:45 And inside that I need to assign it. Okay. So you see it defines a new action like this. And it's
00:23:54 anonymous call because we don't get we don't need any parameter. Actually, it is like here,
00:24:00 as you can see. But this is empty action. And yes, now it should work. Let's try.
00:24:10 OK. All right. I have shown multiple ways to use async and task to do asynchronous programming.
00:24:22 I hope you have enjoyed. Please ask your questions in the comments section. Hopefully see you
00:24:30 in another video. Let me know through comment section that what questions do you have? What
00:24:39 topics do you wonder? What would you like to see in my next video? OK. Hopefully see you later.
Beta Was this translation helpful? Give feedback.
All reactions