I have a long-running method that I call using async/await "all the way down", starting from a button click event handler. However the UI is unresponsive for the duration of the method call, and I've found that the code is running on the UI thread. I'm probably being naive here, but I was under the assumption that await
will always run the method on a b/g thread? I've been using async/await for years but this is the first time I've encountered this issue (luck maybe?!).
I found this article explaining that there are no guarantees the code won't run on the UI thread, but it doesn't seem to explain why. It's probably easier to provide examples from the article rather than my own code, as it's a bit simpler...
The author has this async method:
public static async Task LongProcessAsync()
{
TeenyWeenyInitialization(); // Synchronous
await SomeBuildInAsyncMethod().ConfigureAwait(false); // Asynchronous
CalculateAndSave(); // Synchronous
}
He then goes on to say that calling the method in the following way is fine (i.e. it will always run on a b/g thread):
private async void Button1_Click(object sender, EventArgs args)
{
await Task.Run(async () => await LongProcessAsync());
}
But calling it as seen below (which is what I use in my own code) risks having the awaited method(s) run on the UI thread:
private async void Button1_Click(object sender, EventArgs args)
{
await LongProcessAsync();
}
I'm curious to know why this can happen. I thought the whole point of async/await
was to solve the problem of keeping the UI responsive when calling long-running methods?
Edit
I think a light bulb came on in my head after reading Jakoss's answer. I've been using async/await extensively over the years, but the methods really just contain long-running synchronous code. I assumed that by decorating them with these keywords it would "automagically" run the method asynchronously, to keep the UI responsive. I suspect the only reason why it's worked up until now is that I normally call such a method from the UI tier using await Task.Run(() => SomeMethod());
. Today, I've been tripped up as I've tried to use the simpler await SomeMethod();
.