views:

78

answers:

2

Normally, when I want to cancel a backgroundWorker in C# I will do something like this:

     while (backgroundWorker1.IsBusy)
     {
        backgroundWorker1.CancelAsync();
        autoResetEvent1.WaitOne(BGW_CANCEL_TIMEOUT);
     }

In one application there are a number of backgroundWorkers. Is it valid to use a helper-function to cancel the backgroundWorkers, like so?

CancelBackgroundWorker(BackgroundWorker bgw, AutoResetEvent are)
{
     while (bgw.IsBusy)
     {
        bgw.CancelAsync();
        are.WaitOne(BGW_CANCEL_TIMEOUT);
     }
}

My concern is that instead of passing the objects in question into the function, copies are made, thereby defeating the purpose of having the function. The main purpose of having the function is to reduce code space and make the application code more readable/maintainable.

A: 

Your code is wrong.

Calling CancelAsync merely sets the CancellationPending flag on the BackgroundWorker to true. Your code in the DowWork event is expected to periodically check this flag and stop if the flag is true.

Calling CancelAsync many times will not do any good, and there shouldn't be any reason to freeze the UI thread until it actually cancels.

SLaks
Yes, I realize that. My backgroundWorker has checks in it to look for backgroundWorker1.CancellationPending and exit accordingly. My question is more to the point of are the backgroundWorker1 flags going to be set by the helper function or is it going to set the flags of a copy of the backgroundWorker, which is destroyed when the function returns.
Jim Fell
Since the `BackgroundWorker` class is not a struct, no. All C# classes are always passed by reference. However, the function is useless.
SLaks
@SLaks - Classes are passed by value unless the ref or out keyword is used. For reference types, a copy of the reference is passed.
Chris Dunaway
@Chris: The class is passed by reference; the reference is passed by value.
SLaks
@Slaks - Perhaps it would be clearer to say that a reference to an instance of the class is passed by value. To me, it is confusing to say that the class is passed by reference. For the benefit of others, I refer to Jon Skeet's article: http://www.yoda.arachsys.com/csharp/parameters.html
Chris Dunaway
+2  A: 

No, this isn't okay. It causes deadlock when the BGW has a RunWorkerCompleted event handler. That handler cannot run until the main thread goes idle and re-enters the message loop. The IsBusy property will stay True until that event handler completes.

You have a time-out on the WaitOne call so at least your program won't hang completely. But when WaitOne() returns, the BGW is not yet completed, the RWC event handler hasn't run yet. The only practical alternative is for the RWC event handler to do whatever needs done when the cancellation is complete.

Hans Passant
That was it! Thanks!
Jim Fell