事件驱动的 WPF UI 更新和 C# 中异步接收的最佳做法?



为了学习 c#,我正在编写一个应用程序,该应用程序将持续监视特定端口上的 UDP 流量,并使用收到的数据包信息更新 WPF UI 文本块。以下代码有效(UDP 处理程序类实例d范围内的其他位置实例化):

public MainWindow()
{
InitializeComponent();
Task.Run(async () =>
{
using (d.receiveClient)
{
while (true)
{
var receivedResults = await d.receiveClient.ReceiveAsync();
byte[] buffer = receivedResults.Buffer;
Console.Write("Receiving Data: ");
Console.WriteLine(buffer[0].ToString());
Dispatcher.BeginInvoke(new Action(delegate
{
MyTextBlock.Text = "Rx Data: " + buffer[0].ToString();
}));
}
}
});
}

虽然它有效,但它肯定不会让人觉得惯用或正确。我想创建一个Task<byte[]>,其中包含当前包含receiveClient的类中的异步接收逻辑。问题是它不会连续执行;任务将执行一次,然后退出。我尝试在.ContinueWith()等中重新启动任务,虽然任务可以重新启动,但我似乎松开了 UI 中的钩子。完成事件驱动的连续接收的最佳方式是什么,进而更新本机 c# 中的 WPF UI 组件(我宁愿不使用 WinPcap 或其 .Net 等效项)?

我没有尝试坚持始终运行的任务/线程并将消息传递回主应用程序,而是最终选择将BeginReceive()EndReceive()方法与自定义事件一起使用来处理数据解析。本质上类似于以下内容(提炼为要点):

public void Listen()
{
receiveClient.BeginReceive(new AsyncCallback(ProcessIncoming), null);
}
private void ProcessIncoming(IAsyncResult res)
{
byte[] rec_bytes = receiveClient.EndReceive(res, ref rec_ep);
receiveClient.BeginReceive(new AsyncCallback(ProcessIncoming), null);
PacketReceivedEventArgs args = new PacketReceivedEventArgs();
args.IP = rec_ep.Address;
args.Port = rec_ep.Port;
args.Data = rec_bytes;
OnPacketReceived(args);
}
protected virtual void OnPacketReceived(PacketReceivedEventArgs e)
{
EventHandler<PacketReceivedEventArgs> handler = PacketReceived;
if (handler != null)
{
handler(this, e);
}
}
public event EventHandler<PacketReceivedEventArgs> PacketReceived;
public class PacketReceivedEventArgs : EventArgs
{
public byte[] Data { get; set; }
public IPAddress IP { get; set; }
public int Port { get; set; }
}

在主应用程序中,连接、侦听和数据包处理变为(其中 d 是实现上述方法的类的实例):

d.Connect(someIPString, portInt);
d.PacketReceived += _SomeHandler;
d.Listen();

最新更新