Using async is waiting to freeze the GUI

I would like to handle long running work in a separate thread and return control back to the ASAP GUI thread using the async / await template 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 that it freezes the GUI in any case for 3 seconds (it stops responding 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 the actual project, I have a different long logic than just "Sleep", and it still freezes the GUI, so replacing it with Task.Delay does not solve anything. Also, I don't understand why you should use another command to sleep? How is this required when designing async / wait?

+6
source share
2 answers

You can use Task.Run or Task.Factory.StartNew to execute Test() or some lengthy and / or blocking operations in another thread:

 private async void Button_Click(object sender, RoutedEventArgs e) { await Task.Run(() => Test()); txtResult.Text = "Done!"; } 
+3
source

Used by Thread.Sleep , which blocks the thread. Instead, use Task.Delay , which uses a timer inside and asynchronously returns control 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; } 

Edit

When you posted the new code, I suggest that you isolate the callback that should be launched after the log start process, and save Dispatcher.Invoke and replace it with async-await , which will bring you to the correct 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 } 
+3
source

All Articles