Paul Rivera
Paul Rivera

Reputation: 565

To wait or not to wait inside an AsyncController's Async method

I've seen 2 flavors of working with asyncronous operations in mvc controllers.

First:

public void GetNewsAsync()
{
    AsyncManager.OutstandingOperations.Increment();
    using (ManualResetEvent mre = new ManualResetEvent(false))
    {
        //Perform the actual operation in a worker thread
        ThreadPool.QueueUserWorkItem((object _mre) =>
        {
            //do some work in GetFeed that takes a long time
            var feed = GetFeed();

            AsyncManager.Parameters["Feed"] = feed;
            AsyncManager.OutstandingOperations.Decrement();
            mre.Set();

        }, mre);

        //Wait for the worker thread to finish
        mre.WaitOne(TimeSpan.FromSeconds(SomeNumberOfSecondsToWait));
    }
}

Second:

public void GetNewsAsync()
{
    AsyncManager.OutstandingOperations.Increment();

    //Perform the actual operation in a worker thread
    ThreadPool.QueueUserWorkItem((object x) =>
    {
        //do some work in GetFeed that takes a long time
        var feed = GetFeed();

        AsyncManager.Parameters["Feed"] = feed;
        AsyncManager.OutstandingOperations.Decrement();

    }, null);
}

The first blocks GetNewsAsync for SomeNumberOfSecondsToWait, the second does not. Both perform the work inside a of a worker thread and the results passed to GetNewsCompleted.

So my question is, which is the correct way to handle an Ajax call to GetNews; Wait, or don't wait?

Upvotes: 0

Views: 578

Answers (1)

Darin Dimitrov
Darin Dimitrov

Reputation: 1039298

I don't know where did you see the first example but that's a total anti-pattern that completely defeats the purpose of an asynchronous controller. The whole point of an asynchronous operation is to execute asynchronously and free the main thread as fast as possible.

This being said if GetFeed is a blocking call (which is what its name supposes it is) you get strictly 0 benefit from an asyncrhonous controller so the second example is also wrong for me. You could use a standard synchronous controller action in this case. With the second example you draw a thread from the pool and instead of blocking inside the main thread you block inside the other thread so the net effect is almost the same (in reality it's worse) if you had used a standard synchronous controller action.

So both those examples will bring more overhead than any benefit.

Where asynchronous controllers are useful is when you have some I/O intensive API such as a database or web service call where you could take advantage of IO Completion Ports. The following article provides a good example of this scenario. The newsService used there is providing real asynchronous methods and there is no blocking during the I/O network call. No worker thread being jeopardized.

I would also recommend you reading the following article. Even if it is for classic WebForms it still contains some very useful information.

Upvotes: 2

Related Questions