如果超时,如何安全地终止UdpClient.receive()?

时间:2015-06-25 16:35:14

标签: vb.net multithreading asynchronous timeout

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

this question的答案让我调查了BeginReceive()方法。但是,this question的答案让我很紧张。

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

另外,CancelAsync()文档中的这段代码不太令人放心......

  

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

我想到的一个替代方案是让发送数据包的BackgroundWorker负责超时,然后让它发送某种取消信号包以指示接收者应该停止收听。这样做的问题是,鉴于UDP的性质,不能保证所述数据包将到达,或以正确的顺序被接收。

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

1 个答案:

答案 0 :(得分:2)

我遇到了与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);

    }

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