【问题标题】:await UDPClient.ReceiveAsync with timeout等待 UDPClient.ReceiveAsync 超时
【发布时间】:2012-09-20 05:25:38
【问题描述】:

我正在使用如下所示的 UDPClient

dim c = New UDPClient(port)
client.CLient.ReceiveTimeout = 1
await client.ReceiveAsync()

但是,await 不会终止,甚至不会抛出 虽然我设置了超时。这是正常的吗 行为?

【问题讨论】:

    标签: .net timeout udpclient async-await


    【解决方案1】:

    MSDN 库文章中明确提到了 Socket.ReceiveTimeout:

    获取或设置一个值,该值指定同步 Receive 调用将在多长时间后超时。

    添加了重点。当您使用 ReceiveAsync() 时,您正在执行与同步接收相反的操作。解决方法是使用 System.Timers.Timer 在调用之前启动并在之后停止。在 Elapsed 事件处理程序中关闭套接字,以便 ReceiveAsync() 方法以 ObjectDisposed 异常终止。

    【讨论】:

    • 好主意。当另一个线程正在等待它时,是否存在像这样关闭套接字的任何线程安全问题?
    • 如果没有任何像样的信息,我不可能回答这个问题。然而,让多个线程从套接字异步读取从来都不是问题,这是不可能的。
    【解决方案2】:

    是的。 Socket 上的异步方法不实现超时。如果您需要异步操作超时,您必须自己创建它们(例如,使用 Task.DelayTask.WhenAny)。

    【讨论】:

    • 一个例子可以改善这个答案。
    【解决方案3】:

    我最近遇到了这个问题,我就是这样解决的:

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

    【讨论】:

    • 注意,如果超时,读取仍在运行,最终会丢弃它接收到的数据。只有在超时情况下关闭整个套接字时才能使用此技术。
    猜你喜欢
    • 2012-04-19
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    • 2020-07-19
    • 2016-09-04
    • 2019-07-09
    • 2018-07-29
    • 2011-01-24
    相关资源
    最近更新 更多