views:

465

answers:

3

Hi!

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 cancel 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.

+3  A: 

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)
    {
        ...
    }
}
Thomas Levesque
Ok,when I do My_BgWorker.CancelAsync(); from the page where is executing the backgroundworker it is setting CancellationPending to true and now I amb checking in DoWork this property value.Then when it is true I finish DoWork method but I don't understand one thing: After exit DoWork when RunWorkerCompleted event raises,the argument e as RunWorkerCompletedEventArgs should be e.Cancelled=true and not false because I have done:My_BgWorker.CancelAsync() or I am confused? why I received e.cancelled to false and not to true if I have requested to cancel the background operation with CancelAsync()?
toni
e.Cancel should be set in the DoWork event, if the cancellation request has been taken into account
Thomas Levesque
Yes, in DoWork event I put a break point at the end of it and CancellationPending is set to true but when RunWorkerCompleted event is raised after DoWork finishes, e.Cancelled property in RunWorkerCompleted is false. Is it normal? Shouldn't be true (because I request cancel backgroundworker operation)?
toni
That's what I told you : you need to set e.Cancel to true yourself in DoWork, if you took the cancellation request into account. The value of e.Cancelled in RunWorkerCompleted will reflect the value of e.Cancel in DoWork
Thomas Levesque
Ok! Solved! I was misunderstood you. Sorryyyy. Now It worksssss ;) I received cancelled to false in RunWorkerCompleted ;)Now the only problem I have is what I said to Hanin. Application seems to not exit when I exit of it...Debugging in VS2008 doesn't stop when quiting app.
toni
cancelled to true sorry again by the mistake above
toni
Try to set the ShutdownMode property of your application to OnMainWindowClose
Thomas Levesque
A: 

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.

M.A. Hanin
Ok, I have done what you say, press button pause, but no line is highlihted and In threads window I can see only one process GParts.vshost.exe. After pressing close button application, I can see DoWork method is finished and then RunWorkerCompleted event raised with e.Cancelled argument to false (I don't understand as I said to Thomas why It is not set to true because I do cancelASync()) and the application seems to not exit (no debug stops). In this situation I pause debug, no line is highlighted and I go to thread window where you say and it appears one process.
toni
A: 

Hey!

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.

toni