我有一个线程,它使用UdpClient::BeginReceive
等待来自多个接口的UDP消息和一个调用UdpClient::EndReceive
来回取数据并将其传递的回调。
如果在5秒后我没有得到任何东西,我从调用UdpClient::BeginReceive
的函数返回,以便可以取消该进程并发出另一个广播,这将触发外部客户端发送UDP响应。如果我们没有取消,我会再次调用UdpClient::BeginReceive
函数来检查新数据。
如果客户端没有及时收到任何数据,是否有办法取消该异步请求而不调用无限期阻塞的EndReceive
?我得到的印象是,运行数百个异步触发器是一个坏主意。
答案 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,
),
),
),
);
}
}