2

I've got a BackgroundWorker that occasionally needs to call into the UI thread to perform some work and retrieve a result. To achieve this I'm using the following from within the background thread:

App.Current.Dispatcher.Invoke(new Action(() => { /* some code that updates local data */ });

As the app is exiting, I want to be able to tell the BackgroundWorker to quit but I want to allow it to finish any current operations. In other words, I want to call BackgroundWorkerObj.CancelAsync() and then pump messages until the thread has exited.

I've tried the following, but the Invoke() in the background thread still blocks (though the UI thread is still churning):

Worker.CancelAsync();
while (Worker.IsBusy)
{
    DispatcherFrame Frame = new DispatcherFrame();
    Frame.Continue = false;
    Dispatcher.PushFrame(Frame);
}

What's the correct way to do this? How can the UI thread wait on the BackgroundWorker while still executing Invokes from that BackgroundWorker object?

Salah Akbari
  • 39,330
  • 10
  • 79
  • 109
Bill Brooks
  • 751
  • 1
  • 10
  • 30

2 Answers2

1

This sort of shutdown deadlock is exactly why you shouldn't use Invoke for this purpose.

Change it to BeginInvoke(), and for communications back to the worker thread use an event.

user3690202
  • 3,844
  • 3
  • 22
  • 36
0

I would use Task.Run since you're on .NET 4.0. but anyways. You have to do it the other way around. Wait for the backgroundworker to finish and then exit the application. There is no way to wait for the background thread to finish in an closing event while keeping the main thread responsive. This while loop will block the main thread and message pump until the background thread is done.

Try this

private BackgroundWorker _worker;

protected override OnFormClosing( object sender , FormClosingEventArgs e )
{
  base.OnFormClosing( sender , e );

  // Cancel's the closing and keeps the form alive
  e.Cancel = _worker.IsBusy;
}

private void RunWorkerCompleted( object sender , RunWorkerCompletedEventArgs e)
{
  // Work is done, so close the form
  Close();
}
Sievajet
  • 3,443
  • 2
  • 18
  • 22