【问题标题】:How can I safely terminate UdpClient.receive() in case of timeout?如果超时,如何安全地终止 UdpClient.receive()?
【发布时间】:2015-09-12 09:24:25
【问题描述】:

我想使用 VB.Net 在我的 UDP 多播接收器中实现超时。基本上,如果我在 10 秒内没有收到任何数据包,我想停止收听。我可以很容易地使用间隔为 10000 的Timer 来知道何时需要超时,但问题是如何停止接收功能?如果我使用Receive() 函数(阻止的函数),我可以简单地通过Thread.Abort() 调用来停止它。然而,我所阅读的所有内容都表明这不是一种安全的做法。如果我使用异步BeginReceive() 函数,我不知道如何在它正常完成之前终止它,因为如果没有使用从BeginReceive() 返回的IASyncResult 调用它,EndReceive() 将引发异常。

this question 的答案让我研究了CancelAsync() 方法。但是,this question 的回答让我很紧张。

如果我使用阻塞接收,我将无法连续轮询CancellationPending 属性,除非我从 DoWork 处理程序中在其自己的线程中调用Receive()。但这意味着它会在取消生效后继续运行,对吗?如果我使用BeginReceive(),我担心CancelAsync() 会被DoWork 处理程序“吃掉”,我最终会遇到同样的问题。

另外,BackgroundWorker 文档中的这个 sn-p 并不令人放心......

请注意,您在 DoWork 事件处理程序中的代码可能会在发出取消请求时完成其工作,并且您的轮询循环可能会错过将 CancellationPending 设置为 true 的情况。在这种情况下,您的 RunWorkerCompleted 事件处理程序中 System.ComponentModel.RunWorkerCompletedEventArgs 的 Canceled 标志不会设置为 true,即使已发出取消请求。

我想到的另一种选择是让发送数据包的UdpClient 负责超时,然后让它发送某种取消信号数据包以指示接收器应该停止侦听。这样做的问题是,鉴于 UDP 的性质,无法保证所述数据包会到达,或者以正确的顺序被提取。

有没有办法在 UDP 接收过程完成之前安全地终止它?

【问题讨论】:

    标签: vb.net multithreading asynchronous timeout


    【解决方案1】:

    我在使用 UdpClient 时遇到了同样的问题,我不确定安全解决方案是什么/是否存在“安全”解决方案。但是,我遇到了一个用户为另一个问题发布的函数,该函数跟踪并终止了一个超过特定时间跨度的代码块,我只是将我对 UdpClient.receive() 的调用包含在其中。如果你想尝试一下,函数如下所示:

    private static bool TrackFunction(TimeSpan timeSpan, Action codeBlock)
    {
        try
        {
            Task task = Task.Factory.StartNew(() => codeBlock());
            task.Wait(timeSpan);
            return task.IsCompleted;
        }
        catch (AggregateException ae)
        {
            throw ae.InnerExceptions[0];
        }
    }
    

    你可以像这样简单地将它包裹在你的代码周围:

           bool timeTracker = TrackFunction(TimeSpan.FromSeconds(10), () =>
        {
            Byte[] received = myUdpClient.Receive(ref myIPEndPoint);
    
        }
    

    同样,可能有更好的解决方案,但这正是我所使用的。

    【讨论】:

    • 尽管我最终没有在我的代码中使用这个解决方案,但这是我在任何地方找到的最佳答案,正如它所说的那样。因此,我觉得这个答案应该被接受为正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多