I am trying the async CTP, the versión 4.5 that allow use async methods without needing to write the Begin/End methods.
My first probe is to execute an async method that return void. I see a few 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 to see the results and a button that execute the async method.
In the async method, I use await, that is need because the method is async, and the TasEx.Run to create a new thread in which execute the code.
My doubt is in this point. In a few examples that I see of how to create an async method that returns void, use this way, the Task.Run or TaskEx.Run.
If I am not wrong, Task.Run create a new thread where to execute the method. Then why to use an async method, if with the Task, creating a new thread, I get what I want, not to block the main thread?
Also, if the async method access some shared variable, I must be careful with the concurrency, right? So I don't know the advantage of using async methods, at least in this case.
In fact, I use the same code without async and without await and the result is the same, the main program is not blocking and all works as I expect. The method is this:
private void method01Async()
{
TaskEx.Run(() =>
{
UpdateTxtLog("Enter method01Async: " + System.DateTime.Now);
Thread.Sleep(10000);
UpdateTxtLog("Exit method01Async: " + System.DateTime.Now);
});
}
My question is, this is the correct way to use async when the method return void?
Best Answer
Not exactly.
Task.Run()
will run the code on a thread different from the UI thread (at least with the defaultTaskScheduler
). But it will not actually create a new thread in most cases, it will reuse an existing thread from theThreadPool
.The point of
async
, in the context of a UI application, is to be able to easily execute some code on the UI thread after and asynchronous operation completes.So, if you made your
method01Async
“awaitable”, that is, made it return aTask
:You could then await it from the
btnAsync01_Click
method, if you made it `async:This way, the last line of the method will execute only after the
Task
inmethod01Async
finishes executing. And it will execute on the UI thread.In .Net 4.0, you could achieve similar effect using
ContinueWith()
andDispatcher.Invoke()
:I'm sure you'll agree this is much messier and less readable.
Yes, you're right about that.
The result certainly is not what I thought your code is supposed to do. The last line of
btnAsync01_Click
, will execute “after method01Async”, but it will not wait until theTask
started in that method finishes.As a side note, there is no need to use
async
in yourmethod01Async
. Returning theTask
directly (or not, if you want to keep itvoid
-returning), will work the same: