我想使用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接收过程?
答案 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);
}
同样,可能有更好的解决方案,但这正是我所使用的。