I have created a simple WPF Application and added a button to the default window. When I click on the button, a simulated long working method(simulated using a Thread.Sleep(15000) is called. I am trying to make the button execute asynchronously however despite following online examples, the button and entire window locks as soon as I click and remains so until the Thread.Sleep(...) finishes.
Any ideas why this is happening?
Here is the code:
private void button1_Click(object sender, RoutedEventArgs e)
{
DoSomeAsyncWork();
}
private void DoSomeAsyncWork()
{
System.Windows.Threading.Dispatcher.Run();
Thread thread = new System.Threading.Thread(
new System.Threading.ThreadStart(
delegate()
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => Thread.Sleep(15000)));
}
));
thread.Start();
}
You are putting the long operation back into the UI thread. Let me comment your example:
Thread thread = new System.Threading.Thread(
new System.Threading.ThreadStart(
delegate() {
// here we are in the background thread
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(() => {
// here we are back in the UI thread
Thread.Sleep(15000);
}));
}
));
So, you should modify your example like this:
Thread thread = new System.Threading.Thread(
new System.Threading.ThreadStart(
delegate() {
// here we are in the background thread
Thread.Sleep(15000); // <-- do the long operation here
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(() => {
// here we are back in the UI thread
// do stuff here that needs to update the UI after the operation finished
}));
}
));
As others have mentioned, it's easier to use the BackgroundWorker class. Here's an example:
private void DoSomeAsyncWork()
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (sender, args) => {
// do your lengthy stuff here -- this will happen in a separate thread
Thread.Sleep(15000);
}
bw.RunWorkerCompleted += (sender, args) => {
if (args.Error != null) // if an exception occurred during DoWork,
MessageBox.Show(args.Error.ToString()); // do your error handling here
// do any UI stuff after the long operation here
...
}
bw.RunWorkerAsync(); // start the background worker
}