views:

61

answers:

4

Inside an asp.net mvc 2 controller, I have the following code:

using (BackgroundWorker worker = new BackgroundWorker())
                        {
                            worker.DoWork += new DoWorkEventHandler(blah);
                            worker.RunWorkerAsync(var);
                        }

My question is: is this code async, meaning it launches a new thread and the controller returns the view while 'blah' is executing in parallel?

If not, how would I achieve these results?

A: 

I'm not sure this will work out for you (I'm not saying it won't, just that I'm not sure).

The short answer is yes, the code is asynchronous. But in order to get any kind of return value from a BackgroundWorker, you need to handle its RunWorkerCompleted event.

The basic mechanism is to put some value into the e.Result property in your DoWork event, and then to retrieve it from the e.Result property in your RunWorkerCompleted event (making sure to first check e.Error to see if an exception was thrown in DoWork).

The reason I'm not sure if it'll work out is that you're using the using keyword, which ensures that the BackgroundWorker is disposed of at the end of the code block. Since it is performing its work asynchronously, this may or may not prevent you from ever getting a chance to handle RunWorkerCompleted. I'm really not sure -- maybe somebody else knows?

Dan Tao
A: 

I think you'll probably run into issues as it will try to dispose of the worker while the background thread is still in use. If nothing else, unpredictable behaviour.

Rickster
+4  A: 

In MVC 2 there is a new feature called the AsyncController which is the correct way to do async calls in MVC. Your controller should inherit from AsyncController rather than controller. Then you your primary action method name should have "Async" on the end. for example, if you had an action method called Blah(), you name in BlahAsync() instead and this will be automatically recognized by the framework (and use BlahCompleted() for the callback):

public virtual void BlahAsync()
{
    AsyncManager.OutstandingOperations.Increment();
    var service = new SomeWebService();
    service.GetBlahCompleted += (sender, e) =>
        {
            AsyncManager.Parameters["blahs"] = e.Result;
            AsyncManager.OutstandingOperations.Decrement();
        };
    service.GetBlahAsync();
}

public virtual ActionResult BlahCompleted(Blah[] blahs)
{
    this.ViewData.Model = blahs;
    return this.View();
}

More info on the AsyncController here: MVC AsyncController

Steve Michelotti
A: 

BackgroundWorker isn't really what you want here: there is no UI to update with call backs. You just want to fire off a work item to a thread pool thread and move on.

The ThreadPool.QueueUserWorkItem Method is probably a better fit here, or use the new Task parallel approach: Task.Factory.StartNew(...).

Hightechrider