C# language: Asynchronous
This lesson will require knowledge from the previous one, so if you do not know what concurrency is, go to the concurrency lesson and then come back to this one. Today about asynchronous.
Synchronous vs. asynchronous operations
A synchronous operation does its job before passing the control back to the object or the method that called it.
The asynchronous operation, on the other hand, performs (most) work after transferring control back to the component that called it.
The large majority of the methods you will work with will be synchronous methods, for example, List.Add(), Console.WriteLine(), etc.
Asynchronous methods are less common and initiate concurrency because they work in parallel with the component invoking them.
Asynchronous methods that we have used so far are, for example:
- Thread.Start().
- Task.Run().
- Methods joining the continuation tasks.
What is asynchronous programming?
The principle of asynchrony is that long-running functions are created in an asynchronous manner, ie they are created in a new thread or task in order to apply concurrency.
In an asynchronous approach, there are two benefits:
Conversion can be implemented without threads and as I said in the previous one, which means improved scalability and performance
Large applications contain a smaller amount of code, which increases readability and security.
Asynchronous functions in C
Asynchronous programming introduces two key words async and await keyword, they allow to create asynchronous code, which will have the same structure and simplicity as the synchronous code, and eliminate complexity in the asynchronous code.
For example, the code in the form below:
var result = await expression;
instructions;
It is extended by the compiler to the form of functionality similar to the following:
var awaiter = expression.GetAwaiter();
awaiter.OnCompleted (() =>
{
var result = awaiter.GetResult();
instructions;
});
So, as you can see, it’s less complex.
We will return to this example from the previous lesson:
static void Main()
{
Task<int> primeNumberTask = Task.Run(() =>
{
Thread.Sleep(3000);
return 34;
});
var awaiter = primeNumberTask.GetAwaiter();
awaiter.OnCompleted(() =>
{
int result = awaiter.GetResult();
Console.WriteLine(result); // record of the result
});
Console.ReadKey();
}
With the use of the async and await keywords, the above example will look like this:
static void Main(string[] args)
{
Task<int> primeNumberTask = Task.Run(() =>
{
Thread.Sleep(3000);
return 34;
});
DisplayPrimesCount(primeNumberTask);
Console.ReadKey();
}
static async void DisplayPrimesCount(Task<int> primeNumberTask)
{
int result = await primeNumberTask;
Console.WriteLine(result); // record of the result
}
So as you can see the await keyword simplify very much getting the continuation and legibility of the code, you must always remember about the async keyword in the name of the method, so that it can compile.
We will now see the use of asynchrony in practical solutions, create Windows Forms applications and make a synchronous application in the main file, paste this code:
private void button1_Click(object sender, EventArgs e)
{
for (int i = 1; i < 5; i++)
textBox1.Text += GetPrimesCount(i * 1000000, 1000000) +
" prime numbers between " + (i * 1000000) + " i " + ((i + 1) * 1000000 - 1) +
Environment.NewLine;
}
int GetPrimesCount(int start, int count)
{
return ParallelEnumerable.Range(start, count).Count(n =>
Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i => n % i > 0));
}
This is an example related to calculations, after clicking the “Calculate prime numbers” button, the application hangs, you can not do anything until the application has finished calculating.
So how do you make the application asynchronous so that it does not hang on the calculation?
You have to convert it in this way:
async void button1_Click(object sender, EventArgs e)
{
for (int i = 1; i < 5; i++)
textBox1.Text += await GetPrimesCountAsync(i * 1000000, 1000000) +
" prime numbers between " + (i * 1000000) + " i " + ((i + 1) * 1000000 - 1) +
Environment.NewLine;
}
Task<int> GetPrimesCountAsync(int start, int count)
{
return Task.Run(()=> ParallelEnumerable.Range(start, count).Count(n =>
Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i => n % i > 0)));
}
We have changed the GetPrimesCount() method on asynchronous and we redesigned the function of clicking the button to call the GetPrimesCount() method.
This content also you can find on my blog http://devman.pl/csharplan/c-language-asynchronous/
If you recognise it as useful, share it with others so that others can also use it.
Leave upvote and follow and wait for next articles :) .