.net 你如何';取消';UdpClient::BeginReceive?

.net 你如何';取消';UdpClient::BeginReceive?,.net,asynchronous,c++-cli,udpclient,.net,Asynchronous,C++ Cli,Udpclient,我有一个线程,它使用UdpClient::BeginReceive等待来自多个接口的UDP消息,还有一个回调,调用UdpClient::EndReceive来提取数据并传递 如果5秒钟后我什么也没有得到,我将从调用UdpClient::BeginReceive的函数返回,以便取消该进程并发出另一个广播,该广播将触发外部客户端发送UDP响应。如果不取消,我将再次调用UdpClient::BeginReceive函数检查新数据 如果客户端没有及时接收到任何数据,是否有办法取消该异步请求而不调用End

我有一个线程,它使用
UdpClient::BeginReceive
等待来自多个接口的UDP消息,还有一个回调,调用
UdpClient::EndReceive
来提取数据并传递

如果5秒钟后我什么也没有得到,我将从调用
UdpClient::BeginReceive
的函数返回,以便取消该进程并发出另一个广播,该广播将触发外部客户端发送UDP响应。如果不取消,我将再次调用
UdpClient::BeginReceive
函数检查新数据


如果客户端没有及时接收到任何数据,是否有办法取消该异步请求而不调用
EndReceive
哪个模块会无限期阻塞?我得到的印象是,让数百个异步触发器运行是个坏主意。

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

这将完成BeginReceive()调用,您的回调方法将运行。当调用EndReceive()时,该类让您知道地板垫已消失,并将抛出ObjectDisposedException。因此,要准备好处理此异常,请使用try/catch包装EndReceive()调用,以便捕获ODE并退出回调方法


请注意,这往往会让.NET程序员感到不安,通常强烈不鼓励使用异常进行流控制。但是,您必须调用EndInvoke(),即使您已经知道这将引发异常。否则将导致持续一段时间的资源泄漏。

对于取消
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);
public Task ReceiveAsync(UdpClient客户端,CancellationToken-breakToken)
=>breakToken.IsCancellationRequested
? Task.Run(()=>newudpreciveresult())
:Task.Factory.fromsync(
(回调,状态)=>client.BeginReceive(回调,状态),
(ar)=>
{
if(breakToken.IsCancellationRequested)
返回新的UdpReceiveResult();
IPEndPoint remoteEP=null;
var buffer=client.EndReceive(ar,ref remoteEP);
返回新的UdpReceiveResult(缓冲区、remoteEP);
},
无效);
更多信息请阅读此处:


这也会对我有所帮助:。

这几乎是我发帖后得出的结论。我的实现现在不是最干净的。实际上,我认为我应该让每个接口运行一个侦听器,并且只使用Close()关闭,正如您所建议的,当需要正确处理事情时。谢谢您的确认。欢迎访问SO。请添加更多信息此代码的作用以及解决问题的原因。
      // 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}");
        }
    }