Reputation: 312
I have been trying many different thing and can't get this code to work. My code to stop backgroundworker then close window.
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (bw.IsBusy)
{
bw.CancelAsync();
e.Cancel = true;
MessageBox.Show("close"); //Does show
return;
}
base.OnFormClosing(e);
}
During bw worker
if (worker.CancellationPending)
{
MessageBox.Show("Cancel"); // Does not show
//Cancel
e.Cancel = true;
}
On completed background worker
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Completed"); //Does not work
//Check if restart
if (bw_restart)
{
bw_restart = false;
bw.RunWorkerAsync();
}
//If it was cancelled
if (e.Cancelled)
{
this.Close();
}
//If error show error message
else if (e.Error != null)
{
MessageBox.Show(e.Error.ToString()); // Does not show
}
else //No errors or cancelled
{
MessageBox.Show(e.ToString()); //Does not shoiw
}
}
Cancel button
private void cancel_Click(object sender, EventArgs e)
{
bw.CancelAsync(); //Does not work :s
}
It does not close the window, the X when pressed does not do anything, I got it to close the form but not with stopping the background worker, driving me a bit mad. Link to code i got for this problem that not working: How to stop BackgroundWorker on Form's Closing event?
Upvotes: 0
Views: 912
Reputation: 5093
CancelAsync
doesn't actually abort your thread or anything like that. It sends a message to the worker thread that work should be cancelled via BackgroundWorker.CancellationPending. Your DoWork delegate that is being ran in the background must periodically check this property and handle the cancellation itself.
Look at this:
private BackgroundWorker background;
private void Form1_Load(object sender, EventArgs e)
{
background = new BackgroundWorker();
background.WorkerSupportsCancellation = true;
background.DoWork += BackgroundOnDoWork;
background.RunWorkerCompleted += BackgroundOnRunWorkerCompleted;
background.RunWorkerAsync();
}
private void BackgroundOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs)
{
MessageBox.Show("stop");
}
private void BackgroundOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
// your doWork loop should check if someone don't call background.CancelAsync();
while (!background.CancellationPending)
{
// do something
}
}
private void ButtonClick(object sender, EventArgs e)
{
background.CancelAsync();
}
Upvotes: 0
Reputation: 941327
if (e.Cancelled)
That's fundamentally wrong. You can never be 100% sure that it will be set. Canceling a BGW is always a race condition, the BGW might have been busy exiting when you called its CancelAsync() method so never saw the CancellationPending set to true so never assigned e.Cancel = true in the DoWork event handler.
All you know for a fact is that mClosePending is reliable, since it was set to true on the UI thread. So always call Close() it it is set to true, regardless of the e.Cancelled state.
And yes, checking e.Error doesn't hurt either. But still check mClosePending.
Upvotes: 2
Reputation: 43300
As stated in my comment, your BackgroundWorker has ended due to an error, try adding the following at the top of your run worker completed. Once this error has been resolved your question will be more answerable.
if(e.Error != null)
MessageBox.Show(e.Error.toString());//Put a breakpoint here also
Upvotes: 1