.NET Web Service & BackgroundWorker threads

Pure.Krome picture Pure.Krome · Oct 23, 2008 · Viewed 17.3k times · Source

I'm trying to do some async stuff in a webservice method. Let say I have the following API call: http://www.example.com/api.asmx

and the method is called GetProducts().

I this GetProducts methods, I do some stuff (eg. get data from database) then just before i return the result, I want to do some async stuff (eg. send me an email).

So this is what I did.

[WebMethod(Description = "Bal blah blah.")]
public IList<Product> GetProducts()
{
    // Blah blah blah ..
    // Get data from DB .. hi DB!
    // var myData = .......
    // Moar clbuttic blahs :)  (yes, google for clbuttic if you don't know what that is)

    // Ok .. now send me an email for no particular reason, but to prove that async stuff works.
    var myObject = new MyObject();
    myObject.SendDataAsync();

    // Ok, now return the result.
    return myData;
    }
}

public class TrackingCode
{
    public void SendDataAsync()
    {
        var backgroundWorker = new BackgroundWorker();
        backgroundWorker.DoWork += BackgroundWorker_DoWork;
        backgroundWorker.RunWorkerAsync();
        //System.Threading.Thread.Sleep(1000 * 20);
    }

    private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        SendEmail();
    }
}

Now, when I run this code the email is never sent. If I uncomment out the Thread.Sleep .. then the email is sent.

So ... why is it that the background worker thread is torn down? is it dependant on the parent thread? Is this the wrong way I should be doing background or forked threading, in asp.net web apps?

Answer

Marc Gravell picture Marc Gravell · Oct 23, 2008

BackgroundWorker is useful when you need to synchronize back to (for example) a UI* thread, eg for affinity reasons. In this case, it would seem that simply using ThreadPool would be more than adequate (and much simpler). If you have high volumes, then a producer/consumer queue may allow better throttling (so you don't drown in threads) - but I suspect ThreadPool will be fine here...

public void SendDataAsync()
{
    ThreadPool.QueueUserWorkItem(delegate
    {
        SendEmail();
    });
}

Also - I'm not quite sure what you want to achieve by sleeping? This will just tie up a thread (not using CPU, but doing no good either). Care to elaborate? It looks like you are pausing your actual web page (i.e. the Sleep happens on the web-page thread, not the e-mail thread). What are you trying to do here?

*=actually, it will use whatever sync-context is in place