超时后是否需要调用 EndInvoke?

发布于 2024-07-13 17:21:33 字数 1612 浏览 11 评论 0原文

在网页上,我正在呼叫不允许我以编程方式设置超时的第三方。 我调用 BeginInvoke 并使用 AsyncWaitHandle.WaitOne 等待指定的时间。

如果调用超时,我将继续并忘记我开始的线程调用。 我的问题是,在超时情况下我是否仍然需要以某种方式调用 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;
    }
}

On a web page, I am calling a third party who does not allow me to set timeout programatically. I call BeginInvoke and use the AsyncWaitHandle.WaitOne to wait a specified amount of time.

If the call times out, I move on and forget about the thread call I began. My question is, do I still have to call EndInvoke somehow in a timeout situation? The "CAUTION" remark on this MSDN page makes me wonder if I should: http://msdn.microsoft.com/en-us/library/2e08f6yc(VS.71).aspx

If you believe I should, then the next question is if my web page is done processing and returns to the client before the third party comes back, would the callback method even be there listening to run the code? Doesn't the server stop looking for activitiy once my request/response is done?

Here's the code I'm using:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ゝ杯具 2024-07-20 17:21:33

如果您不调用 EndInvoke,则可能会泄漏一些资源(由 BeginInvoke 分配)。

因此,为了完全安全,请始终调用 EndInvoke() (这会阻塞,因此在不需要的后台线程上执行此操作,或者切换到传递回调,以免在等待时烧毁线程)。

在实践中,我不知道它有多重要(我认为许多 AsyncResults 不会泄漏,所以在这种情况下你可能会幸运并且安全)。

所有这些几乎与请求响应和 Web 服务器等无关,这就是开始/结束编程模型的工作原理,无论您在什么应用程序中使用它。

It's possible that if you don't call EndInvoke, you'll leak some resource (allocated by BeginInvoke).

So to be totally safe, always call EndInvoke() (which will block, so do it on some background thread you don't need, or switch to passing a callback so as not to burn a thread while waiting).

In practice I don't know how often it matters (I think many AsyncResults will not leak, so you may get lucky and be safe in this instance).

All of this has almost nothing to do with request-response and web servers and whatnot, this is just how the Begin/End programming model works, regardless of what application you're using it in.

意中人 2024-07-20 17:21:33

更新:
似乎您需要始终调用 EndInvoke异步调用(除非其 Control.BeginInvoke)或存在泄漏资源的风险。

这是同样的讨论。 建议的解决方案是生成一个线程,等待委托实际完成并调用 EndInvoke。 然而,如果发生真正的超时,我认为该线程就会挂起。

它是一种边缘情况,似乎没有很好地记录下来......也许因为超时不应该发生......特殊情况

Update:
Seems like you need to call EndInvoke always for an async call (unless its Control.BeginInvoke) or risk leaking resources.

Here's a discussion that is on the same lines. The solution suggested is to spawn a thread that will wait for the delegate to actually complete and call EndInvoke. However in case of a really Looong timeout I think that thread would just hang.

Its an edge case that doesn't seem to be documented that well... maybe coz timeouts aren't supposed to happen.. exceptional cases

殊姿 2024-07-20 17:21:33

对于 .NET 异步模式的一般情况,当您不想完成以 BeingXXX 启动的操作时调用 EndXXX 将是一个错误,因为如果在操作完成之前调用 EndXXX,则它应该阻塞直到操作完成。 这对于超时没有太大帮助。

特定的 API 可能会有所不同(例如,WinForms 明确不需要 EndInvoke)。

请参阅“框架设计指南”(第二版)的§9.2。 或者 msdn

For the general case of the .NET async pattern, calling EndXXX when you don't want to complete the operation started with BeingXXX will be a mistake because if EndXXX is called before the operation has completed it should block until it completes. Which isn't much help for a timeout.

A specific API might be different (e.g. WinForms explicitly doesn't require EndInvoke).

See §9.2 of "Framework Design Guidelines" (2nd ed). Or msdn.

像你 2024-07-20 17:21:33

好吧,我不能忽视我到处看到的建议,如果我不确保调用 EndInvoke,我可能会泄漏一些资源,所以我不得不尝试在晚上睡觉,而不用担心我正在接近悬崖。

我找到的解决方案使用了异步回调函数。 如果调用及时返回,我会在那里调用 EndInvoke。 如果没有,我继续单击按钮,并让异步回调函数使用 EndInvoke 清理混乱。

为了回答我自己关于网络应用程序的问题以及“在我超时并继续前进后,是否有人会在那里听”,我发现他们会 - 即使我超时并继续前进,如果我观看了稍后的输出,那么异步即使我已经将输出返回给客户端,调用也会返回并运行回调函数。

我使用了一些我在以下位置找到的内容: http://www.eggheadcafe.com/tutorials/aspnet/847c94bf-4b8d-4a66-9ae5-5b61f049019f/basics-make-any-method-c.aspx

...as以及与我在其他地方找到的回调内容相结合。 这是我下面所做的一个小示例函数。 它结合了我在感谢大家的意见中找到的一些内容!:

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.
        }       

    }
}

Well, I couldn't ignore the advice I saw everywhere that if I did not make sure to call EndInvoke, I MIGHT leak some resources, so I had to try to get that in to sleep at night and not worry I was approaching a cliff.

The solution I found used an async callback function. If the call returned in time, I call EndInvoke there. If not, I continue my button click, and let the async callback function clean up the mess with EndInvoke.

To answer my own question about a web app and "will anyone be there to listen after I time out and move on", I found that they will - even if I timed out and moved on, if I watched the later output, that async call will return and run the call back function, even if I've already returned output to the client.

I used some of what I found at: http://www.eggheadcafe.com/tutorials/aspnet/847c94bf-4b8d-4a66-9ae5-5b61f049019f/basics-make-any-method-c.aspx

...as well as combining with the callback stuff I found elsewhere. Here's a little sample function of what I did below. It combines some of what I found at Thanks for everyone's input!:

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.
        }       

    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文