我在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调用的正确方法;等等,还是不要等?
答案 0 :(得分:2)
我不知道你在哪里看到第一个例子,但这是一个完全违背异步控制器目的的完全反模式。异步操作的重点是异步执行并尽可能快地释放主线程。
如果GetFeed
是一个阻塞调用(这就是它的名字所指的那样),你会得到一个非常好的控制器,所以第二个例子对我来说也是错误的。在这种情况下,您可以使用标准的同步控制器操作。在第二个例子中,你从池中绘制一个线程,而不是阻塞你在另一个线程内阻塞的主线程,所以如果你使用了标准的同步控制器动作,那么净效果几乎是相同的(实际上它更糟)。 / p>
因此,这些例子都会带来比任何好处更多的开销。
在异步控制器有用的情况下,当您有一些I / O密集型API(例如数据库或Web服务调用)时,您可以利用IO完成端口。 following article提供了这种情况的一个很好的例子。在那里使用的newsService
提供了真正的异步方法,并且在I / O网络调用期间没有阻塞。没有工人线程受到危害。
我还建议你阅读following article。即使是经典的WebForms,它仍然包含一些非常有用的信息。