我正在使用以下方式使用UDPClient。
dim c = New UDPClient(port)
client.CLient.ReceiveTimeout = 1
await client.ReceiveAsync()
然而,即使我设置了超时时间,但是等待并没有终止或抛出异常。这种情况正常吗?
dim c = New UDPClient(port)
client.CLient.ReceiveTimeout = 1
await client.ReceiveAsync()
然而,即使我设置了超时时间,但是等待并没有终止或抛出异常。这种情况正常吗?
是的。 Socket
上的异步方法不实现超时。如果需要异步操作超时,您需要自己创建它们(例如,使用Task.Delay
和Task.WhenAny
)。
获取或设置一个值,该值指定同步接收调用超时的时间。
加重强调。当您使用ReceiveAsync()时,您正在执行相反的操作,与同步接收相反。解决方法是使用System.Timers.Timer,在调用前启动计时器,在调用后停止计时器。在已过时间的事件处理程序中关闭套接字,以便ReceiveAsync()方法以ObjectDisposed异常终止。
最近我遇到了这个问题,以下是我的解决方法:
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;
}
技巧在于等待UDP接收任务在Task.WaitAny调用中。