在超时的情况下如何安全终止 UdpClient.receive() ?
How can I safely terminate UdpClient.receive() in case of timeout?
我想使用 VB.Net 在我的 UDP 多播接收器中实现超时。基本上,如果我在 10 秒内没有收到任何数据包,我就想停止收听。我可以很容易地使用间隔为 10000 的 Timer
来知道何时需要超时,但问题是如何停止接收功能?如果我使用 Receive()
函数(阻塞的函数),我可以简单地通过调用 Thread.Abort()
来停止它。然而,我读过的所有内容都表明这不是一种安全的做法。如果我使用异步 BeginReceive()
函数,我不知道如何在它正常完成之前终止它,因为如果不使用 IASyncResult
调用 EndReceive()
将抛出异常从 BeginReceive()
.
返回
this question led me to investigate the CancelAsync()
method. But, the answer to this question的答案让我很紧张。
如果我使用阻塞接收,我将无法连续轮询 CancellationPending
属性,除非我从 DoWork 处理程序中在它自己的线程中调用 Receive()
。但这意味着它会在取消生效后继续 运行 对吗?如果我使用 BeginReceive()
,我担心 CancelAsync()
会被 DoWork 处理程序获取 "eaten",我最终会遇到同样的问题。
此外,BackgroundWorker
文档中的这段代码并不令人放心...
Be aware that your code in the DoWork event handler may finish its work as a cancellation request is being made, and your polling loop may miss CancellationPending being set to true. In this case, the Cancelled flag of System.ComponentModel.RunWorkerCompletedEventArgs in your RunWorkerCompleted event handler will not be set to true, even though a cancellation request was made.
我想到的一个替代方案是让发送数据包的 UdpClient
负责超时,然后让它发送某种取消信号数据包以指示接收方应该别听了。这样做的问题是,鉴于 UDP 的性质,无法保证所述数据包一定会到达,或者以正确的顺序被提取。
有没有办法在 UDP 接收过程完成之前安全地终止它?
我 运行 遇到了与 UdpClient 相同的问题,我不确定存在什么安全解决方案 is/if 和 "safe" 解决方案。但是,我遇到了一个用户针对不同问题发布的函数,该函数跟踪并终止超过特定时间跨度的代码块,我只是将对 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);
}
同样,可能有更好的解决方案,但这只是我使用的。
我想使用 VB.Net 在我的 UDP 多播接收器中实现超时。基本上,如果我在 10 秒内没有收到任何数据包,我就想停止收听。我可以很容易地使用间隔为 10000 的 Timer
来知道何时需要超时,但问题是如何停止接收功能?如果我使用 Receive()
函数(阻塞的函数),我可以简单地通过调用 Thread.Abort()
来停止它。然而,我读过的所有内容都表明这不是一种安全的做法。如果我使用异步 BeginReceive()
函数,我不知道如何在它正常完成之前终止它,因为如果不使用 IASyncResult
调用 EndReceive()
将抛出异常从 BeginReceive()
.
this question led me to investigate the CancelAsync()
method. But, the answer to this question的答案让我很紧张。
如果我使用阻塞接收,我将无法连续轮询 CancellationPending
属性,除非我从 DoWork 处理程序中在它自己的线程中调用 Receive()
。但这意味着它会在取消生效后继续 运行 对吗?如果我使用 BeginReceive()
,我担心 CancelAsync()
会被 DoWork 处理程序获取 "eaten",我最终会遇到同样的问题。
此外,BackgroundWorker
文档中的这段代码并不令人放心...
Be aware that your code in the DoWork event handler may finish its work as a cancellation request is being made, and your polling loop may miss CancellationPending being set to true. In this case, the Cancelled flag of System.ComponentModel.RunWorkerCompletedEventArgs in your RunWorkerCompleted event handler will not be set to true, even though a cancellation request was made.
我想到的一个替代方案是让发送数据包的 UdpClient
负责超时,然后让它发送某种取消信号数据包以指示接收方应该别听了。这样做的问题是,鉴于 UDP 的性质,无法保证所述数据包一定会到达,或者以正确的顺序被提取。
有没有办法在 UDP 接收过程完成之前安全地终止它?
我 运行 遇到了与 UdpClient 相同的问题,我不确定存在什么安全解决方案 is/if 和 "safe" 解决方案。但是,我遇到了一个用户针对不同问题发布的函数,该函数跟踪并终止超过特定时间跨度的代码块,我只是将对 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);
}
同样,可能有更好的解决方案,但这只是我使用的。