等待或不等待AsyncController的异步方法

时间:2011-11-22 19:06:41

标签: asp.net-mvc multithreading asynccontroller

我在mvc控制器中看到过2种使用异步操作的风格。

首先:

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));
    }
}

第二

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);
}

第一个阻止SomeNumberOfSecondsToWait的GetNewsAsync,第二个阻止。两者都在一个工作线程中执行工作,结果传递给GetNewsCompleted。

所以我的问题是,这是处理对GetNews的Ajax调用的正确方法;等等,还是不要等?

1 个答案:

答案 0 :(得分:2)

我不知道你在哪里看到第一个例子,但这是一个完全违背异步控制器目的的完全反模式。异步操作的重点是异步执行并尽可能快地释放主线程。

如果GetFeed是一个阻塞调用(这就是它的名字所指的那样),你会得到一个非常好的控制器,所以第二个例子对我来说也是错误的。在这种情况下,您可以使用标准的同步控制器操作。在第二个例子中,你从池中绘制一个线程,而不是阻塞你在另一个线程内阻塞的主线程,所以如果你使用了标准的同步控制器动作,那么净效果几乎是相同的(实际上它更糟)。 / p>

因此,这些例子都会带来比任何好处更多的开销。

在异步控制器有用的情况下,当您有一些I / O密集型API(例如数据库或Web服务调用)时,您可以利用IO完成端口。 following article提供了这种情况的一个很好的例子。在那里使用的newsService提供了真正的异步方法,并且在I / O网络调用期间没有阻塞。没有工人线程受到危害。

我还建议你阅读following article。即使是经典的WebForms,它仍然包含一些非常有用的信息。