2009-02-17 57 views
8

在網頁上,我打電話給不允許我以編程方式設置超時的第三方。我調用BeginInvoke並使用AsyncWaitHandle.WaitOne等待指定的時間。超時後我需要調用EndInvoke嗎?

如果通話超時,我繼續前進,並忘記了我開始的線程調用。我的問題是,我是否仍然需要在超時情況下以某種方式調用EndInvoke?在此MSDN頁面上的「注意」備註讓我想知道我是否應該:http://msdn.microsoft.com/en-us/library/2e08f6yc(VS.71).aspx

如果您認爲我應該,那麼接下來的問題是如果我的網頁在第三方回來之前完成處理並返回到客戶端,回調方法甚至會在那裏偵聽運行代碼?一旦我的請求/響應完成,服務器不會停止尋找活動嗎?

下面是我使用的代碼:

public class RemotePaymentProcessor 
{ 
    private delegate string SendProcessPaymentDelegate(string creditCardNumber); 

    private string SendProcessPayment(string creditCardNumber) 
    { 
     string response = string.Empty; 
     // call web service 
     SlowResponseService.SlowResponseService srs = new WebServiceTimeout.SlowResponseService.SlowResponseService(); 
     response = srs.GetSlowResponse(creditCardNumber); 
     return response; 
    } 

    public string ProcessPayment(string creditCardNumber, int timeoutMilliseconds) 
    { 
     string response = string.Empty; 

     SendProcessPaymentDelegate sppd = new SendProcessPaymentDelegate(SendProcessPayment); 
     IAsyncResult ar = sppd.BeginInvoke(creditCardNumber, null, new object()); 
     if (!ar.AsyncWaitHandle.WaitOne(timeoutMilliseconds, false)) 
     { 
      // Async call did not return before timeout 
      response = "TIMEOUT"; 
     } 
     else 
     { 
      // Async call has returned - get response 
      response = sppd.EndInvoke(ar); 
     } 
     return response; 
    } 
} 

回答

0

那麼,我不能忽視我在各處看到的建議,如果我不確定調用EndInvoke,我可能會泄漏一些資源,所以我不得不在晚上嘗試讓它進入睡眠狀態,而不用擔心我正在接近懸崖。

我發現的解決方案使用了異步回調函數。如果該呼叫及時返回,我在那裏調用EndInvoke。如果沒有,我繼續點擊按鈕,並讓異步回調函數清理EndInvoke的混亂。

要回答我自己關於網絡應用程序的問題和「任何人在我超時後繼續聽下去」時,我發現他們會 - 即使我超時並繼續前進,如果我觀看了更晚的輸出,異步調用將返回並運行回調函數,即使我已經將輸出返回給客戶端。

我使用了一些什麼,我發現在:http://www.eggheadcafe.com/tutorials/aspnet/847c94bf-4b8d-4a66-9ae5-5b61f049019f/basics-make-any-method-c.aspx

...以及與回調的東西,我在別處找到了結合。以下是我在下面做的一些示例函數。它結合了一些什麼,我在感謝發現每個人的投入!:

public class RemotePaymentProcessor 
{  
    string currentResponse = string.Empty; 

    private delegate string SendProcessPaymentDelegate(string creditCardNumber);  
    private string SendProcessPayment(string creditCardNumber)  
    {   
     SlowResponseService.SlowResponseService srs = new WebServiceTimeout.SlowResponseService.SlowResponseService();   
     string response = srs.GetSlowResponse(creditCardNumber);   
     return response;  
    }  

    public string ProcessPayment(string creditCardNumber, int timeoutMilliseconds)  
    {   
     string response = string.Empty;   
     SendProcessPaymentDelegate sppd = new SendProcessPaymentDelegate(SendProcessPayment);   
     IAsyncResult ar = sppd.BeginInvoke(creditCardNumber, new AsyncCallback(TransactionReturned), sppd);   
     if (!ar.AsyncWaitHandle.WaitOne(timeoutMilliseconds, false))   
     {    
      // Async call did not return before timeout    
      response = "TIMEOUT";   
     }   
     else    
     {    
      // Async call has returned - get response    
      response = sppd.EndInvoke(ar);   
     }   

     currentResponse = response; // Set class variable 
     return response;  
    } 

    private void TransactionReturned(IAsyncResult ar) 
    { 
     string response = string.Empty; 

     // Get delegate back out of Async object 
     SendProcessPaymentDelegate sppd = (SendProcessPaymentDelegate)ar.AsyncState; 

     // Check outer class response status to see if call has already timed out 
     if(currentResponse.ToUpper().Equals("TIMEOUT")) 
     { 
      // EndInvoke has not yet been called so call it here, but do nothing with result 
      response = sppd.EndInvoke(ar); 
     } 
     else 
     { 
      // Transaction must have returned on time and EndInvoke has already been called. Do nothing. 
     }  

    } 
} 
1

更新:
好像你需要call EndInvoke always一個異步調用(除非其Control.BeginInvoke)或風險泄漏資源。

這是a discussion that is on the same lines。建議的解決方案是產生一個線程,等待委託實際完成並調用EndInvoke。但是,如果發生Looong超時,我認爲該線程會掛起。

它的一個邊緣的情況下,似乎並沒有被證明是很好...也許怎麼把超時是不應該發生的..特殊情況下

2

這是可能的,如果你不調用EndInvoke,你會泄露一些資源(由BeginInvoke分配)。因此爲了完全安全,總是調用EndInvoke()(它會阻塞,所以在一些不需要的後臺線程上執行,或者切換到傳遞迴調以便在等待期間不燒斷線程)。

在實踐中,我不知道它的重要性(我認爲許多AsyncResults不會泄漏,所以在這種情況下您可能會很幸運並且安全)。

所有這一切都幾乎無關,與請求 - 響應和web服務器和諸如此類的東西,這是多麼的你在使用什麼應用中開始/結束編程模型作品,不管。

+0

關於請求 - 響應:如果我傳遞一個回調方法,但在平均時間完成我的buttonclick功能,並返回到客戶端,有沒有任何人在BeginInvoke線程返回時監聽?在本地應用程序中,如果Main()完成並關閉應用程序,則回調從未被觸發。 – Chad 2009-02-17 18:28:21

0

對於.NET異步模式的一般情況,當您不想完成以BeingXXX開頭的操作時調用EndXXX將是一個錯誤,因爲如果在操作完成之前調用EndXXX,它應該阻塞直到它完成。這對於超時沒有太大的幫助。

特定的API可能會有所不同(例如WinForms顯式不需要EndInvoke)。

參見「框架設計指南」(第2版)的第9.2節。或者msdn