Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make BackgroundWorker return an object

In your DoWork event handler for the BackgroundWorker (which is where the background work takes place) there is an argument DoWorkEventArgs. This object has a public property object Result. When your worker has generated its result (in your case, a List<FileInfo>), set e.Result to that, and return.

Now that your BackgroundWorker has completed its task, it triggers the RunWorkerCompleted event, which has a RunWorkerCompletedEventArgs object as an argument. RunWorkerCompletedEventArgs.Result will contain the result from your BackgroundWorker.

example:

private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
    int result = 2+2;
    e.Result = result;
}

private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    int result = (int)e.Result;
    MessageBox.Show("Result received: " + result.ToString());
}

I'm assuming that you don't want to block and wait on RunWorkerAsync() for the results (if you did, there would be no reason to run async!

If you want to be notified when the background process finishes, hook the RunWorkerCompleted Event. If you want to return some state, return it in the Result member of DoWork's event args.

Example:



    private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
      // do your thing
      ....
      // return results
      e.Result = theResultObject;
    }
    
    // now get your results
    private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      MyResultObject result = (MyResultObject)e.Result;
      // process your result...
    }



RunWorkerAsync() starts the process asynchronously and will return and continue executing your code before the process actually completes. If you want to obtain the result of the BackgroundWorker, you'll need to create an instance variable to hold that value and check it once the BackgroundWorker completes.

If you want to wait until the work is finished, then you don't need a BackgroundWorker.


To add to David's answer, one may want to push a tuple through to provide more than one argument to the methods.

To do so let me update his answer, where a value (called engagementId) is passed through each of the calls and the tuple holds that original item for use as well as the result.

private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
    var engagementId = (int)e.Argument;
    int result = 2 + 2;
    e.Result = (engagementId, result);
}

private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    (int engagementId, int result) tupleResult = ((int, int)) e.Result; // Both (( are needed for tuple/casting.

    MessageBox.Show($"Result received {tupleResult.result} for engagement {tupleResult.engagementId}");
}

See the answer to How To Cast To A Tuple for more information.