Introduction
In this series, we will try to understand the benefits of Async/Await keyword while working on Asynchronous programming.
I am going to cover this topic in two parts:
- Basic concepts and common terminology used
- Best practices for Async/Await to make your application more efficient
Basic Concept and common terminology used
Async/Await are contextual keywords, which are used by new generation apps to take advantage of Asynchronous Programming. Although these are wrappers on the task library which makes the code more readable and easier to maintain.
These keywords also increase the chances of increased EXCEPTION, which is possibly untracked, and potentially introduces a deadlock in an application if not used properly.
When we talk about Task/Threads, two terms are always used, Thread Pool and State Machine. What exactly are these?
Thread Pool
This is where all threads sit in a machine. Basically, two types of thread will be maintained by CLR in the Thread pool.
- Worker thread:
Just refers to any thread other than the main thread that does some 'work' on behalf of the application that spawned the thread. 'Work' could really mean anything, including waiting for some I/O to complete. The thread pool keeps a cache of worker threads because threads are expensive to create.
- Asynchronous I/O thread:
The term 'I/O thread' in .NET/CLR refers to the threads the Thread Pool reserves in order to dispatch Native Overlapped callbacks from "overlapped" win32 calls (also known as "completion port I/O"). The CLR maintains its own I/O completion port and can bind any handle to it (via the ThreadPool.BindHandle API).
State Machine
The state machine is where task will be executed and will reference which thread initiated that task so that when that task is completed, the state machine will notify the caller thread that the task has finished.
Async Keyword
Async indicate that this method will be executed asynchronously. It will run in State machine. When we add the "Async" keyword in method signature, the compiler will create a class based on method name inherited that from State Machine interface.
Await Keyword
Every Task should be awaited. If not, then executing the thread won't wait for that Task, which is executing asynchronously. Basically, it returns to caller thread with reference to ongoing task and stop execution of code below that line and release the current thread to thread pool to process another request.
Async and await are always used together, if not, then there will be something wrong.
Dead Locks
When the UI thread is waiting to complete some asynchronous task, and inside that Async method, we are trying to reflect something in UI control, then we have created a deadlock.
In a Web application, when we say Task is running in State machine, it means the state machine is running on a UI thread. If we use SomeAsyncMethod().Wait(), the UI thread is a block and the State machine now does not know the returning caller Thread and application will be in the deadlock stage.
Let’s see some code:
I have a WPF app that has one Btn click event and one label to display the text.
In the below code, are you able to identify the problem?
private void RunApp_Click(object sender, RoutedEventArgs e)
{
var t1 = Task.Run(() =>
{
OutPutText.Text = "This text will be set from different thread.....!!!!!";
});
}
Correct, we aren't able to see the text assigned to OutPutText(Label) control, so there will be no error thrown to the surface. If this is not working code, then we should get error. We will see where the error has gone in a moment.
What is problem in above code?
The UI thread will invoke the Task and will run to completion without waiting for "t1" task to complete and when task "t1" which will go to write text in the label marked as completed and try to assign a value on a label control that it cannot.
Why was the exception not thrown if this is not working code?
The task is running on the State machine. If there is an exception on the task, it will shallow by Task itself because the whole code will be executed inside a try-catch block. The below code shows the compile version of “RunApp_Click". I highlighted some important pieces in yellow.
[CompilerGenerated]
private sealed class <RunApp_Click>d__1 : IAsyncStateMachine
{
public int <>1__state;
public AsyncVoidMethodBuilder <>t__builder;
public object sender;
public RoutedEventArgs e;
public MainWindow <>4__this;
private Task <t1>5__1;
private void MoveNext()
{
int num = this.<>1__state;
try
{
this.<t1>5__1 = Task.Run(new Action(this.<>4__this.<RunApp_Click>b__1_0));
}
catch (Exception exception)
{
this.<>1__state = -2;
this.<>t__builder.SetException(exception);
return;
}
this.<>1__state = -2;
this.<>t__builder.SetResult();
}
[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
}
}
How to track exception in this scenario?
Task lib has a method called "ContinueWith", which will execute when the Task marks itself as competed, either with a success or failure.
private async void RunApp_Click(object sender, RoutedEventArgs e)
{
var t1 = Task.Run(() =>
{
OutPutText.Text = "This text will be set from different thread.....!!!!!";
});
t1.ContinueWith(t =>
{
if (t.IsFaulted)
{ /*Handel the exception*/}
});
}
Time to see the solution of above problem
Basically we have many ways to solve this problem. We will see some of the best ways.

Benson OnyangoPosted Dec 11, 2020, 12:29 AM
Hi, You are really a guru in C#! whats does this mean before compilation private async void timer1_Tick(object sender, EventArgs e) { frmConnect.<timer1_Tick>d__3 variable = null; AsyncVoidMethodBuilder asyncVoidMethodBuilder = AsyncVoidMethodBuilder.Create(); asyncVoidMethodBuilder.Start<frmConnect.<timer1_Tick>d__3>(ref variable); }
Benson OnyangoPosted Dec 11, 2020, 12:29 AM
Hi, I see that you are guru in C#. Am a beginner. Could you please interpret for me this piece of compiled code Hi, You are really a guru in C#! whats does this mean before compilation private async void timer1_Tick(object sender, EventArgs e) { frmConnect.<timer1_Tick>d__3 variable = null; AsyncVoidMethodBuilder asyncVoidMethodBuilder = AsyncVoidMethodBuilder.Create(); asyncVoidMethodBuilder.Start<frmConnect.<timer1_Tick>d__3>(ref variable); }
srinivas madicharlaPosted Jun 3, 2020, 12:20 AM
Good one...The article is very informative