2009-02-17 33 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