I have a WPF application. In the window closing event i need to call an async method with return value that itself needs to access UI components.
To run this code, create a fresh wpf application, add this line to the MainWindow.xaml
Closing="Window_Closing"
and this code to the MainWindow.xaml.cs
private async void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Console.WriteLine("Start");
// while the method is awaited, Window_Closing gives the control back to the caller
// since Window_Closing is void, WPF goes on and closes the application
// before the long running task has been finished => FAIL
var result = await Test();
// creates a dead lock. Breakpoint on the Task.Delay(1000) is hit
// then nothing happens and the application is locked => FAIL
var result = Test().Result;
// Task.Delay(1000) works, but when the Background shall be accessed...
// "The calling thread cannot access this object because a different thread owns it."
// => Fail
var result = Task.Run(() => Test()).Result;
// same like the first try.
// WPF goes on and closes the application
// before the result has ever been set => FAIL
var result = false;
await Application.Current.Dispatcher.BeginInvoke(async () =>
{
result = await Test();
});
Console.WriteLine(result);
e.Cancel = result;
}
public async Task<bool> Test()
{
await Task.Delay(1000);
this.Background = Brushes.AliceBlue;
return true;
}
How (without changing the Test method) do i get the desired/expected behavior?