I do some tests with the new asynchronous pattern of C# 5.0 (async/await) I have a problem with understanding how the asynchronous methods are called.
Considering this code :
private async Task<string> DownloadAsync()
{
progress.ProgressChanged += (s, e) =>
{
progressBar1.Value = e.value;
};
return await DownloadSomething(myurl, progress);
}
private async void CallDownloadAsync()
{
string text = await DownloadAsync();
progressBar1.Value = 0;
label1.Text = "Done!";
}
private void button4_Click(object sender, EventArgs e)
{
CallDownloadAsync();
}
So, this code works very well. When I clic the "button4" a downloading task begins and my ProgressBar is updated correctly.
But, I'd like to compact my code a little bit more by removing CallDownloadAsync() method like this :
private void button4_Click(object sender, EventArgs e)
{
new Action(async () =>
{
string result = await Task.Run<string>(() => DownloadAsync());
}).Invoke();
label1.Text = "Running...";
}
So here, I want to directly initiate an action which calls the DownloadAsync method but when I hit my Button4 I have a Cross-thread operation not valid on the progressBar. So I do not understand what is the main difference between the Action() and the call of my CallDownloadAsync() method.
The difference is that in former case you call
CallDownloadAsync()
from UI thread (context).In the latter case,
DownloadAsync()
is called from the initiated Task which is generally executed in a different thread created by TPL (Task Parallel Library) out of UI thread or threads created from it.In WPF, UI components can be accessed only by a dedicated UI thread or (its children) threads created from under it (i.e with the same UI context).
You may find my
async
/await
intro helpful. In particular, anasync
method does not run on a background thread;Task.Run
is used to run something on a background thread, hence the difference in your code.In general, you should avoid
async void
, unless you're writing anasync
event handler. Like this: