2011-11-22 235 views
0

我見過兩種口味的mvc控制器中的異步操作。等待或不等待一個AsyncController的異步方法

第一:

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

第一塊GetNewsAsync爲SomeNumberOfSecondsToWait,第二不。兩者都在一個工作者線程中執行工作,並將結果傳遞給GetNewsCompleted。

所以我的問題是,這是處理GetNews的Ajax調用的正確方法;等等,還是不要等待?

回答

2

我不知道你在哪看到第一個例子,但這是一個完全違反異步控制器目的的完全反模式。異步操作的重點在於異步執行並儘可能快地釋放主線程。

這就是說,如果GetFeed是一個阻塞調用(這是它的名字假設它是),你得到嚴格的0從一個異步控制器的好處,所以第二個例子對我來說也是錯誤的。在這種情況下,您可以使用標準的同步控制器操作。在第二個示例中,您從池中繪製一個線程,而不是在主線程內部阻塞,從而阻塞其他線程,因此如果使用了標準的同步控制器操作,則淨效果幾乎相同(實際上更糟糕)。

所以這兩個例子都會帶來比任何好處更多的開銷。

異步控制器很有用的地方在於當您有一些I/O密集型API(如數據庫或Web服務調用)時,您可以利用IO完成端口。 following article提供了這種情況的一個很好的例子。這裏使用的newsService提供了真正的異步方法,並且在I/O網絡調用期間沒有阻塞。沒有工作線程受到危害。我也建議您閱讀following article。即使它是用於傳統的WebForms,它仍然包含一些非常有用的信息。

+0

GetFeed不一定必須是阻塞調用,它可能有它自己的定時/超時處理。重點是,可能需要1秒鐘的時間才能返回,或者1分鐘。至於第一個的使用,我在使用ajax長輪詢的聊天服務器的實現中看到了它,就像彗星一樣。 –

+0

@PaulRivera,如果'GetFeed'是一個非阻塞的調用,你將無法像調用第二個示例那樣在調用它之後立即使用它的結果。在調用'GetFeed'之後,您將無法立即將'feed'結果分配給'AsyncManager.Parameters'。非阻塞API與回調一起工作。它不返回結果。所以'GetFeed'被阻塞或者你的第二個例子不正確。 –

+0

好的,所以GetFeed會在等待發生的情況下阻塞x秒。我真正需要知道的是,第一個例子是否正確,特別是對於ajax長輪詢場景。我的意思是,如果在Async方法中沒有Wait,那麼可以肯定地說ajax調用在Completed方法返回數據之前不會返回? –