你怎么'取消'UdpClient :: BeginReceive?

时间:2013-08-19 09:00:53

标签: .net asynchronous c++-cli udpclient

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

如果在5秒后我没有得到任何东西,我从调用UdpClient::BeginReceive的函数返回,以便可以取消该进程并发出另一个广播,这将触发外部客户端发送UDP响应。如果我们没有取消,我会再次调用UdpClient::BeginReceive函数来检查新数据。

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

3 个答案:

答案 0 :(得分:12)

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

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

请注意,这往往会让.NET程序员感到有些不安,因此通常强烈建议不要使用流控制的异常。但是你来调用EndInvoke(),即使你已经知道这会引发异常。如果不这样做,将导致资源泄漏,可能会持续一段时间。

答案 1 :(得分:0)

对于取消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 correct early termination

这也是有用的:Is it safe to call BeginXXX without calling EndXXX if the instance is already disposed

答案 2 :(得分:0)

import 'package:flutter/material.dart';

class TempMyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Test App',
      home: Scaffold(
        backgroundColor: Colors.indigo.shade800,
        appBar: AppBar(
          title: Text(
            'Test App',
          ),
          elevation: 0,
          backgroundColor: Colors.indigo.shade800,
        ),
        body: Container(
          decoration: BoxDecoration(
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(60),
              topRight: Radius.circular(60),
            ),
            color: Colors.white,
          ),
        ),
      ),
    );
  }
}