0

我已经在 mvc 控制器中看到了两种使用异步操作的方式。

第一的:

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 调用的正确方法;等,还是不等?

4

1 回答 1

2

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

这就是说如果GetFeed是一个阻塞调用(这是它的名字所假设的),你从异步控制器中获得严格的 0 好处,所以第二个例子对我来说也是错误的。在这种情况下,您可以使用标准同步控制器操作。在第二个示例中,您从池中绘制一个线程,而不是在主线程内阻塞,而是在另一个线程内阻塞,因此如果您使用标准同步控制器操作,净效果几乎相同(实际上它更糟)。

所以这两个例子都会带来比任何好处更多的开销。

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

我还建议您阅读以下文章。即使它是针对经典 WebForms 的,它仍然包含一些非常有用的信息。

于 2011-11-22T19:14:13.063 回答