wpf cancel backgroundworker on application exits
In my application I have a main windows and into it, in a frame I load a page. This page do a long time task when the user press a button. My problem is that when long task is being doing and the user presses the close button of the main window, the application seems to not finish because I am debugging it in VS2008 and I can see the stop button highlighted. If I want to finish I have to press stop button, the application doesn't stop the debugging automatically on application exit. I thought .NET stops automatically backgroundworkers on application exits but I am not sure after seeing this behaviour. I have tried to force and ca开发者_高级运维ncel background worker in unloaded event page with something like this:
private void Page_Unloaded(object sender, RoutedEventArgs e)
{
// Is the Background Worker do some work?
if (My_BgWorker != null && My_BgWorker.IsBusy)
{
//If it supports cancellation, Cancel It
if (My_BgWorker.WorkerSupportsCancellation)
{
// Tell the Background Worker to stop working.
My_BgWorker.CancelAsync();
}
}
}
but with no success. After doing CancelAsync(), a few minutes after, I can see the backgroundworker finishes and raise RunWorkerCompleted and I can see the task is completed checking e.Cancelled argument in the event but after this event is exectued the application continues without exiting and I have no idea what is doing....
I set WorkerSupportsCancellation to true to support cancel at the begining.
I would apreciate all answers. Thanks.
Cancellation is not automatic, your code in the DoWork
event handler needs to handle the cancellation by checking the value of the CancellationPending
property. Calling CancelAsync
doesn't abort the thread, it merely sets CancellationPending
to true...
For instance :
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
while(!bgw.CancellationPending)
{
...
}
}
I think Thomas Levesque pinpointed the issue.
On a general note: somewhere, some thread is still executing. You can try and find out what thread that is, by pausing the debug process (pause button, named "Break All"). At this point, the next code line executed should be highlighted. Also, you can use the Threads window (under Debug -> Windows) to see exactly which thread is still running, and where.
Perfect Thomas, setting ShutdownMode to OnMainWindowClose as you said solved my problem. Now debugger stops correctly ;) Thanks very much for helping me.
What I did is:
<Application
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
x:Class="GParts.App"
StartupUri="WinMain.xaml"
ShutdownMode="OnMainWindowClose">
<...>
</Application>
Finally I would like to do one thing respect to backgroundworker in DoWork event in case an exception is thrown by some type of error: I hanlde errors inside it with a try catch clause and into catch I do:
catch (Exception ex)
{
e.Result = ex.Message;
}
When backgroundworker finishes by an exception I want in RunWorkerCompleted to detect it with e.Error and show it. So what I do in RunWorkerCompleted is:
if (e.Cancelled)
{
// Cancelled
}
else if (e.Error != null)
{
// Exception Thrown
// Here I want to show the message that produced the exception in DoWork
// event. If I set e.Result = ex.Message in DoWork event, is e.Error here
// containing ex.Message?
}
else
{
// Completed);
}
Is e.Error in RunWorkerCompleted containing ex.Message?
Thanks.
精彩评论