3

The following code adds the numbers from 1 to 100 and returns the sum. What I'm trying to do is run the calculations in a backgroundworker and return a value. The problem with this is that returnValue is returned before DoWork completes. How can I have it wait for my background worker to complete before returning a value? (I can't seem to put the return in my DoWork...)

double returnValue = 0;

var b = new BackgroundWorker();
b.DoWork += new DoWorkEventHandler(
    delegate(object sender, DoWorkEventArgs e) {
        for(int i=0;i<100;i++){
            returnValue += (i+1);
        }
    }
);

b.RunWorkerAsync();
return returnValue;

Addendum: Would it be better to send a message pump on the same thread instead of running this on a background worker?

Also, this is just example code, my actual code takes more than a minute to complete.

sooprise
  • 22,657
  • 67
  • 188
  • 276
  • 1
    Almost the same question as http://stackoverflow.com/questions/939635/how-to-make-backgroundworker-return-an-object – Doc Brown Mar 07 '11 at 19:37
  • Possible duplicate http://stackoverflow.com/questions/5182782/c-return-value-from-function-invoked-in-thread/5201814#5201814 – Sanjeevakumar Hiremath Mar 07 '11 at 19:37
  • 1
    What you're asking to do doesn't make sense; you're trying to execute code on the `BackgroundWorker`, but you also want to block the calling method from returning until the `BackgroundWorker` is done. – Adam Robinson Mar 07 '11 at 19:38

5 Answers5

3

Subscribe to the RunWorkerCompleted event. That event contains the return value of the background operation.

Of course, that value would be returned from inside the DoWorkEventHandler, like so:

b.DoWork += new DoWorkEventHandler(
    delegate(object sender, DoWorkEventArgs e) {
        double returnValue = 0;
        for(int i=0;i<100;i++){
            returnValue += (i+1);
        }
        e.Result = returnValue;
    }
);
Jon
  • 428,835
  • 81
  • 738
  • 806
  • Yes this works well. I also like that the return value can be an object or struct. – mtone Mar 07 '11 at 19:41
  • 1
    not worked.error DoWorkEventHandler returns void, a return keyword must not be followed by an object – Mohsen.Sharify Nov 08 '16 at 05:26
  • @BeeLabeille seems I wrote the "return" wrong, although after so many years I have no idea what I was thinking at the time. Anyway, setting `e.Result` is correct. – Jon Oct 15 '20 at 14:24
  • @Jon Yes, you are right. After a bit of digging around yesterday I eventually realised that what I needed to use was the Result property, hence my suggested answer – BeeLabeille Oct 16 '20 at 08:13
0

I don't really see a question here, but what I think you are looking for is the event called RunWorkerCompleted. That gets raised when the DoWork delegate completes. If this is not what you are looking for, I think you need to rephrase your question.

Bryan
  • 2,775
  • 3
  • 28
  • 40
0

i have postet a sample: here maybe it can help you :-)

Also, this is just example code, my actual code takes more than a minute to complete.

this can be the effect of the async start. you can tell the backgroundworker when to start or just say start. if you don´t explicit say that he should start NOW he starts when c# thinks it is a good time to start :-)

Community
  • 1
  • 1
jwillmer
  • 3,570
  • 5
  • 37
  • 73
0

If, like me, you were not able to use the accepted answer because DoWorkEventHandler returns void, the code below might help.

double returnValue = 0;
var b = new BackgroundWorker();
b.DoWork += PerformJob;
b.RunWorkerCompleted += JobDone;

private void PerformJob(object sender, DoWorkEventArgs args)
{
    // Pre-Processing: for-loop to increment returnValue
    /*
    ** DoWorkEventArgs has a 'Result' object with the following description
    ** Summary: Gets or sets a value that represents the result of an asynchronous operation.
    ** Returns: An System.Object representing the result of an asynchronous operation.
    */
    args.Result = returnValue;
}

private void JobDone(object sender, RunWorkerCompletedEventArgs args)
{
    //RunWorkerCompletedEventArgs also has a 'Result' object like DoWorkEventArgs
    double updatedReturnValue = (double)args.Result;

    // Post-processing: e.g. use updatedReturnValue to update a text block, show a message box etc.
}
BeeLabeille
  • 174
  • 1
  • 4
  • 16
  • Note that the accepted answer has now been edited to reflect the use of the 'Result' property instead of the 'return' statement – BeeLabeille Oct 16 '20 at 08:14
-1

You are trying to do a synchronous operation with BackgroundWorker which it BAD. But if you must, you could use the IsBusy flag.

double returnValue = 0;

var b = new BackgroundWorker();
b.DoWork += new DoWorkEventHandler(
    delegate(object sender, DoWorkEventArgs e) {
        for(int i=0;i<100;i++){
            returnValue += (i+1);
        }
    }
);

b.RunWorkerAsync();
while(b.IsBusy){
  Application.DoEvents();
}
return returnValue;
Bala R
  • 107,317
  • 23
  • 199
  • 210
  • 1
    This kinda defeats the purpose of the BackgroundWorker. – Bryan Mar 07 '11 at 19:36
  • @Bryan exactly. but if he has to wait for the BackgroundWorker to finish then why use BackgroundWorker ? – Bala R Mar 07 '11 at 19:37
  • Would a message pump be better? – sooprise Mar 07 '11 at 19:40
  • @sooprise like `Application.DoEvents();` ? sure – Bala R Mar 07 '11 at 19:44
  • 1
    Calling Application.DoEvents is almost always a bad idea. msdn tries to make this clear but does not, imho, put sufficient emphasis on how bad an idea it is. http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents.aspx – Adam Straughan Mar 07 '11 at 19:54
  • @adam The OP's situation is not traditional. Why create a BgWorker to add items and wait for the result when you can just have the for loop just in the method and return value. I know it's bad practice and I have indicated that in my answer. I'm assuming the OP is just experimenting with BackgroundWorker and I'm trying to answer the OP without trying to make suggestions of good practices. – Bala R Mar 07 '11 at 20:01
  • @adam here's a better article on DoEvents() http://www.codinghorror.com/blog/2004/12/is-doevents-evil.html – Bala R Mar 07 '11 at 20:03