Asynchronous programming in C #. Introduction.

Many people have heard of this, but not many use it in their code. Meanwhile, no serious programs with client-server architecture will do without asynchronous programming. Exchange of data with the database, the interaction of the client and the server - this takes time, which can be occupied by other processes instead of waiting.

When the operation is executed synchronously, the thread is blocked by another thread. And we have to wait for the implementation of this second process to return control to the first one. This causes unnecessary waste of resources, because a stream with a single task can wait for a long time to respond. From a database, for example, or a web service.

And if temporary resources can save multi-threading (the benefit of modern processors allows it), then memory resources will not save it. After all, in fact, multi-threading is also synchronous execution of operations. Just there are few of them.

The real solution is to use asynchronous processing. With this approach, we can use several threads to control one or the other.

That is, while waiting for a response from another task, the current one does not block the thread, but provides it to another task.

Let's look at the picture:

 

In this case, a single-threaded asynchronous approach is used.

And here a multi-threaded asynchronous stream.

 

Each thread performs many tasks. When one of the tasks stops in anticipation, another one is taken. Thus, tasks flow from one thread to another, depending on the one that was freed first. The figure shows that Task 1 started executing in the first thread, and finished in the second.

Let's consider one more figure - a sequence diagram:

 

The diagram describes the behavior of threads for a client-server application. The client sends a request for data from the server, and instead of "hanging" waiting for the response (as in the synchronous approach) continues to work, providing the user with another application functionality. So, if you are a web developer, then without asynchrony you can do nothing.

Let's understand a little in theory. There are three patterns of asynchronous programming:

Asynchronous Programming Model appeared in the first version of the .Net Framework. APM allowed to create asynchronous versions of synchronous methods using two methods - Begin <MethodName> and End <MethodName>.

So, there are only two methods:

1
2
3
4
public IAsyncResult Begin{MethodName}(TIn[] args, AsyncCallback callback, object userState =null) 
{ 

}

 And:

1
2
3
4
public TResult End{MethodName}(IAsyncResult result) 
{ 
... 
}

 The Begin{MethodName} method starts an asynchronous operation. It takes the parameters args, callback - the delegate to the method called after the asynchronous method is executed, the userState object, which is used to transfer information about the state of a particular application to the method called when the asynchronous operation ends.

The method returns an object of type IAsyncResult that stores information about an asynchronous operation.

The End{MethodName} method terminates the asynchronous operation. It takes an input object, type IAsyncResult, and returns TResult, which actually returns the type defined in the synchronous copy of this method.

Let's see how this template is used in a simplified example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void Button_Click (...)
{
WebRequest request = WebRequest.Create(url);
request.BeginGetResponse(Callback , request);
}
 
public void Callback(IAsyncResult ar)
{
WebRequest request = (WebRequest) ar.AsyncState;
try
{
var response = request.EndGetResponse(ar); // Code does something with successful response
}
catch (WebException e)
{
// Error handling code
}
}

 We called the Begin method in the button click event handler. As a parameter, we pass a callback to this method. And, already in the callback itself we call the pair method - End.

The disadvantages of the asynchronous programming model include:

 

Event-based Asynchronous Pattern

This pattern of asynchronous programming appeared in the second version of the .Net framework. It is based on events and asynchronous methods. The class that implements this template will contain the methods MethodNameAsync and MethodNameAsyncCancel (if operation cancellation processing is required), and the MethodNameCompleted event. In the same class, you can place synchronous versions of methods that work with the same thread. Most often this template is used when working with web services. For example, ajax implements the Event-based Asynchronous Pattern. You can get the result of an asynchronous operation and process errors only in the MethodNameCompleted event handler.

The asynchronous programming pattern based on events solved some problems of the predecessor:

• Declaration a method to get the result of an asynchronous operation;

• There is no mechanism for notification of the progress of the operation.

However, this template still has a number of drawbacks:

• It is not possible to transfer the context of the operation call (user data) to the result processing method;

• Not all operations can be interrupted. Methods that support only one operation in the queue cannot be interrupted;

• It is not possible to specify in the context of which thread callback methods will be called.


Task-based Asynchronous Pattern (TAP)

The third template for asynchronous programming appeared in .Net Framework 4.0. From the title it is clear that it is based on the use of tasks. The basis of TAP is two types of System.Threading.Tasks.Task and System.Threading.Tasks.Task <TResult>.

TAP allows developers to define asynchronous functions within a single method. Now there is no need to create the functions of the beginning and the end of the asynchronous operation, and then also the callback. This of course facilitates the work of the programmer, reduces the threshold of entry into the technology, and simply makes programming pleasant.

TAP uses tasks to perform operations. For each task, a separate thread is used, which is taken from the thread pool. After the task is completed, the thread returns to the pool.

The modifier "async" - this modifier is applied to a method or lambda expression, or an anonymous method - it indicates that the method is asynchronous and signals the possibility of one or more occurrences of the wait statement in this method.

Let's have a look at an example of a method definition:

1
2
3
4
5
6
public async Task<int>MyProcessAsync()
{

Var Overtime = await new ERP().ProcessOvertime(emp);

}

 Note the keywords async and await. These are operators that signal that the Task-based Asynchronous Pattern is being used. The async modifier indicates that the method is asynchronous. And the await statement can be called inside the method one or more times. It suspends the execution of the task until the result is obtained, while the thread continues its work.

And here is an example of using TAP from life. Calling the web service:

1
2
3
4
5
6
7
static async Task<string> SendMessageAsync()
{
var client = new MyServiceClient();
var task = Task.Factory.StartNew(() => client.SendMessageAsync("Message"));
var result = await task;
return result;
}

 And here is another way of calling, even simpler and more understandable:

1
2
3
4
5
6
static async Task<string> SendMessageAsyncNew()
{
var client = new MyServiceClient();
var result = await client.SendMessageAsync("Message");
return result;
}

 This "lightweight" version of using await is available in the .Net Framework 4.5.

The asynchronous task-based approach solved most of the problems of the previous templates. Then you and the ability to interrupt the asynchronous operation, and a simple implementation of one method, the ability to track the progress of the operation.

Currently, Microsoft recommends using this template to implement asynchronous calls when developing components.

As for the expediency of using this template. Using TAP will increase the bandwidth of the server. However, the cost of creating an asynchronous process can offset benefits if you have a small amount of traffic (for example, a client-server). In this case, the synchronous approach will work faster.

I understand that we have just "ran through the tops" and this information is not enough for a good understanding of how different approaches to asynchronous programming work. And therefore, we'll look at each template in detail, in subsequent articles.

Fast Reports
  • 800-985-8986 (English, US)
  • +4930568373928 (German)
  • +55 19 98147-8148 (Portuguese)
  • info@fast-report.com
  • 901 N Pitt Str #325 Alexandria VA 22314

© 1998-2024 Fast Reports Inc.
Trustpilot