I would like to handle long running operation in separate thread and return control back to GUI thread ASAP using async/await pattern as follows:
private async void Button_Click(object sender, RoutedEventArgs e)
{
await Test();
txtResult.Text = "Done!";
}
private Task Test()
{
Thread.Sleep(3000);
return Task.FromResult(0);
}
The problem is, it freezes GUI anyway for 3 seconds (it becomes unresponsive until Done! is displayed after 3 seconds). What am I doing wrong?
EDIT: I am trying to replace the following logic:
private void Button_Click(object sender, RoutedEventArgs e)
{
var thread = new Thread(() => Test(Callback));
thread.Start();
}
private void Callback()
{
Dispatcher.Invoke(() =>
txtResult.Text = "Done!");
}
private void Test(Action callback)
{
Thread.Sleep(3000); //long running operation, not necessarily pause
callback();
}
In actual project I have different long running logic than just Sleep, and it still freezes GUI, so replacing it with Task.Delay does not solve anything. Besides, I don't get why you should use yet another command for Sleep? How is this required by async/await design?
You can use Task.Run
or Task.Factory.StartNew
to execute Test()
or some long running and/or blocking operation on another thread:
private async void Button_Click(object sender, RoutedEventArgs e)
{
await Task.Run(() => Test());
txtResult.Text = "Done!";
}
You're using Thread.Sleep
which blocks the thread.
Use Task.Delay
instead, which uses a timer internally and asynchronously yields control back to the caller:
private async void Button_Click(object sender, RoutedEventArgs e)
{
await TestAsync();
txtResult.Text = "Done!";
}
private async Task<int> TestAsync()
{
await Task.Delay(3000);
return 0;
}
As you posted new code, I suggest you isolate the callback that needs to run after the log running process, and save yourself the Dispatcher.Invoke
and replace it with the use of async-await
which will land you on the right synchronization context for you:
private async void Button_Click(object sender, RoutedEventArgs e)
{
await Task.Run(Test);
CallBack();
}
private void Callback()
{
txtResult.Text = "Done!"
}
private void Test()
{
Thread.Sleep(3000); //long running operation, not necessarily pause
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With