When the method returns void, the same as the task?

I am trying to use async CTP, version 4.5, which allows you to use async methods without having to write Begin / End methods.

My first probe is to execute the async method, which returns void. I see some examples and do the following:

private void btnAsync01_Click(object sender, RoutedEventArgs e) { UpdateTxtLog("click button: " + System.DateTime.Now); method01Async(); UpdateTxtLog("after ethod01Async: " + System.DateTime.Now); } private async void method01Async() { await TaskEx.Run(() => { UpdateTxtLog("Enter method01Async: " + System.DateTime.Now); Thread.Sleep(10000); UpdateTxtLog("exit method01Async: " + System.DateTime.Now); }); } 

In my WPF project, I have a textBox where you can see the results and the button that execute the async method.

In the async method, I use await, this is necessary because the isync method, and TasEx.Run, to create a new thread in which the code is executed.

My doubt is that. In the few examples that I see about how to create an async method that returns void, use this method: Task.Run or TaskEx.Run.

If I'm not mistaken, Task.Run create a new thread where the method should be executed. Then why use the async method, if using Task, creating a new thread, I get what I want, so as not to block the main thread?

Also, if the async method accesses some shared variable, I have to be careful with concurrency, right? Therefore, I do not know the benefits of using asynchronous methods, at least in this case.

In fact, I use the same code without async and without waiting, and the result is the same, the main program does not block, and everything works as I expect. The method is as follows:

 private void method01Async() { TaskEx.Run(() => { UpdateTxtLog("Enter method01Async: " + System.DateTime.Now); Thread.Sleep(10000); UpdateTxtLog("Exit method01Async: " + System.DateTime.Now); }); } 

My question is, is this the correct way to use async when the method returns void?

+6
source share
2 answers

If I'm not mistaken, Task.Run create a new thread where the method should be executed.

Not really. Task.Run() will run the code in a thread other than the user interface thread (at least by default TaskScheduler ). But in most cases, it will not actually create a new thread, it will reuse the existing thread from ThreadPool .

Then why use the async method, if using Task, creating a new thread, I get what I want, so as not to block the main thread?

The async point, in the context of the UI application, should be able to easily execute some code in the user interface thread after the asynchronous operation is completed.

So, if you made your method01Async "expected", that is, made it return Task :

 private async Task method01Async() { await Task.Run(/* whatever */); } 

Then you can wait for it from the btnAsync01_Click method if you made it `async:

 private async void btnAsync01_Click(object sender, RoutedEventArgs e) { UpdateTxtLog("click button: " + System.DateTime.Now); await method01Async(); UpdateTxtLog("after method01Async: " + System.DateTime.Now); } 

Thus, the last line of the method will be executed only after the completion of the Task in method01Async . And it will execute in the user interface thread.

In .Net 4.0, you can achieve a similar effect with ContinueWith() and Dispatcher.Invoke() :

 private void btnAsync01_Click(object sender, RoutedEventArgs e) { UpdateTxtLog("click button: " + System.DateTime.Now); method01Async().ContinueWith(() => Dispatcher.Invoke( new Action(() => UpdateTxtLog("after method01Async: " + System.DateTime.Now))); } 

I am sure you will agree that this is a lot of messy and less readable.

Also, if the async method accesses some shared variable, I have to be careful with concurrency, right?

Yes, you are right about that.

In fact, I use the same code without async and without waiting, and the result is the same, the main program does not block, and everything works as I expect.

The result, of course, is not what I thought your code should do. The last line of btnAsync01_Click will execute "after the 01Async method", but will not wait for the Task to complete in this method.


As a side note, there is no need to use async in method01Async . Returning the Task directly (or not, if you want to keep it void -returning) will work the same way:

 private Task method01Async() { return Task.Run(/* whatever */); } 
+3
source

In fact, you are not using async in any way, since you are not expecting an initial call. Here's how you should do it:

 private async void btnAsync01_Click(object sender, RoutedEventArgs e) { UpdateTxtLog("click button: " + System.DateTime.Now); await method01Async(); UpdateTxtLog("after ethod01Async: " + System.DateTime.Now); } private async Task method01Async() { return await TaskEx.Run(() => { UpdateTxtLog("Enter method01Async: " + System.DateTime.Now); Thread.Sleep(10000); UpdateTxtLog("exit method01Async: " + System.DateTime.Now); }); } 

As soon as you change it to this (an important part of await method01Async() ) in the button click event, it will return there after it exits, and in your text log “after that” a 10 second delay will be displayed for 10 seconds, your “exit01Async method "logged in method01Async .

+1
source

Source: https://habr.com/ru/post/912590/


All Articles