I have WinForms app where button click calls some async method of external library.
private async void button1_Click(object sender, EventArgs e)
{
await CallLibraryAsync();
}
private static async Task CallLibraryAsync()
{
var library = new Library();
await library.DoSomethingAsync();
}
The library looks like this:
public class Library
{
public async Task DoSomethingAsync()
{
Thread.Sleep(2000);
await Task.Delay(1000).ConfigureAwait(false);
// some other code
}
}
Before any asynchronous code there is some calculation simulated by Thread.Sleep
call. In that case this call will block UI thread for 2 seconds. I have no option to change the code in DoSomethingAsync
.
If I want to solve blocking problem, I could call the library in Task.Run
like this:
private static async Task CallLibraryAsync()
{
var library = new Library();
// added Task.Run
await Task.Run(() => library.DoSomethingAsync());
}
It solves the problem, UI is not blocke anymore, but I've consumed one thread from ThreadPool. It is not good solution.
If I want to solve this problem without another thread, I can do something like this:
private static async Task CallLibraryAsync()
{
var library = new Library();
// added
await YieldOnlyAsync().ConfigureAwait(false);
await library.DoSomethingAsync();
}
// added
private static async Task YieldOnlyAsync()
{
await Task.Yield();
}
This solution works. Task.Yield()
causes that method YieldOnlyAsync()
always runs asynchronously and ConfigureAwait(false)
causes that next code (await library.DoSomethingAsync();
) runs on some ThreadPool thread, not UI thread.
But it is quite complicated solution. Is there any simpler?
Edit:
If the library method looks like this
public class Library
{
public async Task DoSomethingAsync()
{
await Task.Delay(1000).ConfigureAwait(false);
Thread.Sleep(2000);
await Task.Delay(1000);
// some other code
}
}
UI thread would not be blocked and I do not need to do anything. But that's the problem that it is some implementation detail I do not see directly because that could be in some nuget package. When I see that the UI freezes in some situations, I may find this problem (mean CPU-bound calculation before any await in async method) just after some investigation. There is no Wait()
or Result
, that would be easy to find, this is more problematic.
What I would like is to be prepared for that situation if possible in some simpler way. And that's why I do not want to use Task.Run
whenewer I call some third-party library.