我想知道当我的UdpClient接收数据时是否有任何方法可以以某种方式触发事件? (System.Net.Sockets.UdpClient)
我尝试覆盖它的UdpClient.Receive,但我无法根据this,因为可覆盖的成员必须标记为虚拟或抽象。
我目前正在这样做的方法是在Threading.Timer上以特定的时间间隔运行TimerCallback来获取我的数据,但我更愿意接收传入的数据,而不是重复获取数据。
有关我如何执行此操作的任何建议,建议或指示,或者我是否必须按时间间隔手动接收?
提前致谢。
答案 0 :(得分:4)
覆盖Receive
方法无论如何都不会帮助你 - 它不是UDP客户端接收数据时调用的方法,它是一种方法当你想等待输入数据时,你打电话。
但是,Receive
方法会阻止。这意味着您不必每隔一段时间检查一次 - 您可以简单地检查(几乎)无限循环。只是在不同的主题中进行。
void Loop(CancellationToken token)
{
var remoteEP = default(IPEndPoint);
while (!token.IsCancellationRequested)
{
var data = client.Receive(ref remoteEP);
yourForm.Invoke(DataReceived, data);
}
}
当然,由于这是简单的I / O,因此无需占用线程来执行此操作 - 您可以使用异步I / O:
public Task Loop(CancellationToken token)
{
using (UdpClient client = new UdpClient(80))
{
while (!token.IsCancellationRequested)
{
var data = await client.ReceiveAsync();
// Process the data as needed
}
}
}
在winforms或WPF应用程序中,这将自动运行 - 您只需在btnStart_Click
事件处理程序中使用此代码,它将在后台等待数据时保持您的UI响应;每当数据返回时,它将在UI线程上执行其余的代码(Process the data as needed
) - 无需手动创建任何线程或处理调度。
当然,处理终止有点棘手,但使用UDP总是很棘手 - 基本上,你要么必须使用支持取消的更手动的方式({{1 }}只是ReceiveAsync
和BeginReceive
不支持取消的包装器,或者您使用设置取消令牌然后发送0长度的旧技巧数据包给自己(导致EndReceive
调用结束并返回零长度字节数组。)
答案 1 :(得分:3)
您也可以使用Rx Extensions接收数据。
将ReceiveAsync
中的UpdClient
换成Observable.FromAsync
并订阅可观察对象。
UdpClient client = new UdpClient(..., ...);
var obs = Observable.FromAsync(client.ReceiveAsync);
var sub = obs.Subscribe(...);
答案 2 :(得分:2)
UdpClient.Receive阻止执行,直到它从端点接收数据。但是有一个异步的替代品,UdpClient.BeginReceive。它不完全是一个事件,但以类似的方式工作,您可以封装它并激活您自己的事件。可以在此处找到文档(带代码示例):http://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.beginreceive(v=vs.110).aspx