我正在使用UDPClient,如下所示
dim c = New UDPClient(port)
client.CLient.ReceiveTimeout = 1
await client.ReceiveAsync()
但是,等待不会终止或抛出甚至虽然我已经设置了超时。这正常吗行为?
MSDN Library 文章中明确提到了 Socket.ReceiveTimeout:
获取或设置一个值,该值指定同步接收调用超时的时间量。
强调添加。 当你使用 ReceiveAsync() 时,你正在做与同步接收相反的事情。 解决方法是使用在呼叫之前启动并在呼叫之后停止的 System.Timers.Timer 。 关闭 Elapsed 事件处理程序中的套接字,以便 ReceiveAsync() 方法以 ObjectDispose 异常终止。
是的。Socket
上的异步方法不实现超时。如果您需要异步操作超时,则必须自己创建它们(例如,使用 Task.Delay
和 Task.WhenAny
)。
我最近遇到了这个问题,这就是我解决它的方式:
async Task Listen(IPEndPoint ep, int timeout)
{
using (var udp = new UdpClient(ep))
{
var result = await Task.Run(() =>
{
var task = udp.ReceiveAsync();
task.Wait(timeout);
if (task.IsCompleted)
{ return task.Result; }
throw new TimeoutException();
});
Receive(result); // use the result
}
}
对于它的价值,这就是我的做法(也可能使用取消令牌的组合):
public static async Task<byte[]> SendReceiveUdpAsync(IPEndPoint endPoint, byte[] packet, int timeout, CancellationToken cancellationToken)
{
using var client = new UdpClient(endPoint.AddressFamily);
await client.SendAsync(packet, endPoint, cancellationToken).ConfigureAwait(false);
var task = client.ReceiveAsync(cancellationToken);
var index = Task.WaitAny(new [] { task.AsTask() }, timeout, cancellationToken);
if (index < 0)
return null;
return task.Result.Buffer;
}
诀窍是在 Task.WaitAny 调用中等待 UDP 接收任务。