6

I have a thread which sits around waiting for UDP messages from multiple interfaces using UdpClient::BeginReceive and a callback which calls UdpClient::EndReceive to pick up the data and pass it on.

If after 5 seconds I don't get anything, I return from the function which calls UdpClient::BeginReceive so that the process can be cancelled and to issue another broadcast which would trigger external clients to send in UDP responses. If we're not cancelling, I call the UdpClient::BeginReceive function again to check for new data.

If the client hasn't received any data in time, is there a way to cancel that async request without calling EndReceive which blocks indefinitely? I get the impression that leaving hundreds of async triggers running would be a bad idea.

4

3 回答 3

15

您需要猛拉地板垫,调用 UdpClient.Close() 方法。

这将完成 BeginReceive() 调用,并且您的回调方法将运行。当您调用 EndReceive() 时,该类会告知您地垫已消失,并将引发 ObjectDisposedException。所以准备好处理这个异常,用 try/catch 包装 EndReceive() 调用,这样你就可以捕获 ODE 并退出回调方法。

请注意,这往往会让 .NET 程序员有点不高兴,通常强烈建议不要使用异常进行流控制。然而,您必须调用 EndInvoke(),即使您已经知道这会引发异常。不这样做会导致资源泄漏,可能会持续一段时间。

于 2013-08-19T13:08:19.540 回答
1

对于取消BeginRecieve,您可以使用Close方法,但在基本实现中它将调用ObjectDisposedException. 我通过创建自定义来修复它,BeginRecieve这是基础实现的现代化:

public Task<UdpReceiveResult> ReceiveAsync(UdpClient client, CancellationToken breakToken)
    => breakToken.IsCancellationRequested
        ? Task<UdpReceiveResult>.Run(() => new UdpReceiveResult())
        : Task<UdpReceiveResult>.Factory.FromAsync(
            (callback, state) => client.BeginReceive(callback, state),
            (ar) =>
                {
                    if (breakToken.IsCancellationRequested)
                        return new UdpReceiveResult();

                    IPEndPoint remoteEP = null;
                    var buffer = client.EndReceive(ar, ref remoteEP);
                    return new UdpReceiveResult(buffer, remoteEP);
                },
            null);

在此处阅读更多内容:UdpClient.ReceiveAsync 正确提前终止

这也将有所帮助:如果实例已被释放,则在不调用 EndXXX 的情况下调用 BeginXXX 是否安全

于 2016-12-09T14:09:15.610 回答
0
      // Set ReadMsg = true while using UdpClient
      // Set ReagMsg = false before Dispose or Close no Exception Error
      private static bool ReadMsg;
      private static void ReceiveCallback(IAsyncResult ar)
      {

        UdpClient u = (UdpClient)((UdpState)(ar.AsyncState)).u;
        IPEndPoint e = (IPEndPoint)((UdpState)(ar.AsyncState)).e;
        try
        {
            if ( ReadMsg )
            {
                Byte[] receiveBytes = u.EndReceive(ar, ref e);
                string sddpMessage = Encoding.ASCII.GetString(receiveBytes);

            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"{ex.Message}");
        }
    }
于 2020-04-12T07:10:12.140 回答