如何在超时的情况下安全地终止UdpClient.received()



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

这个问题的答案使我开始研究CancelAsync()方法。但是,这个问题的答案让我很紧张。

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

此外,BackgroundWorker文档中的这个片段也不太令人放心。。。

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

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

有没有一种方法可以在UDP接收过程结束之前安全地终止它?

我在UdpClient中遇到了同样的问题,我不确定安全的解决方案是什么/是否存在"安全"的解决方案。然而,我遇到了一个用户为另一个问题发布的函数,该函数跟踪并终止超过特定时间跨度的代码块,我只是将对UdpClient.rereceive()的调用封装在其中。如果你想尝试一下,该函数看起来像这样:

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

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

我遇到过类似的情况,我打开了与远程设备的几个连接(Udp、Serial等),并需要在它们之间切换;听众";使用阻塞CCD_ 15调用的线程。调用Thread.Abort()导致崩溃,在不首先退出线程的情况下切换连接实例(UdpClient)也不起作用,因为线程挂在UdpClient.Receive()上,while循环中的一个简单标志从未退出。

最终起作用的是关闭主应用程序线程中的连接,这将导致UdpClient.Receive()抛出一个可以捕获和处理的异常。应用程序创建代表各种连接的CCD_ 19的实例;听众";可以通过设置全局标志并关闭当前CCD_ 20实例来终止的线程。我使用了VB.NET,它看起来像这样:

Dim mListening as Boolean    'application flag for exiting Listener thread 
Dim mReceiver as UdpClient   'a connection instance 
...
Private Sub Listener()
    While mListening
        Try
            Dim reply = mReceiver.Receive()
        Catch ex As Exception
            'execution goes here when mReceiver.Close() called
        End Try
    End While
End Sub

应用程序设置mListening并启动Listener线程。当应用程序需要";解锁";则它调用mReceiver.Close()并相应地处理它。我毫无问题地使用了这个方案。我正在使用VS 2019和。NET v4.7

相关内容

  • 没有找到相关文章

最新更新