线程上的UDP侦听器并发送到GUI

本文关键字:GUI 并发 侦听器 UDP 线程 | 更新日期: 2023-09-27 18:03:49

我正在运行一个基于对话框的程序,该程序定期发送TCP,但也侦听UDP消息并将内容显示给GUI。对于我最初使用的简单示例,一旦我开始在while中侦听(true),所有其他GUI功能都将关闭。然后我尝试生成一个线程来执行侦听,但是这些示例要求我创建一个新类,该类将GUI元素从视图中隐藏起来。

所以我的问题是,什么是侦听UDP消息和写内容到GUI而不阻塞GUI线程的最佳实践?

线程上的UDP侦听器并发送到GUI

您需要让代码在某种类型的后台线程中执行侦听。这很简单,有很多的方式字符串一个后台线程,从Thread类,BackgroundWorker, Task, ThreadPool.QueueUserWorkItem(虽然在你的情况下一个线程池线程是不合适的,你需要一个完整的线程,因为你的操作是长时间运行),等等。

之后你所需要的就是更新UI的方式。同样,有几种方法可以做到这一点(有些是特定于你正在使用的UI功能的(WPF, winform等),有些则不是。

使用IProgress<T>特别有用,特别是因为它不依赖于特定的UI技术。在UI中创建Progress对象,并指定当有特定结果时如何更新UI,将对象传递给后台worker,并在接收到信息时让它Report进程。

一个例子可能像这样:

private void Form1_Load(object sender, EventArgs e)
{
    Progress<string> progress = new Progress<string>();
    progress.ProgressChanged += data =>
    {
        textBox1.AppendText(data);
    };
    Thread tcpListener = new Thread(() => ListenForData(progress));
    tcpListener.Start();
}
private void ListenForData(IProgress<string> progress)
{
    while (true)
    {
        Thread.Sleep(1000);//placeholder for real IO to get data
        progress.Report("data");
    }
}

如果你没有c# 4.5,创建你自己的Progress类是很简单的:

public interface IProgress<T>
{
    void Report(T data);
}
public class Progress<T> : IProgress<T>
{
    SynchronizationContext context;
    public Progress()
    {
        context = SynchronizationContext.Current
            ?? new SynchronizationContext();
    }
    public Progress(Action<T> action)
        : this()
    {
        ProgressReported += action;
    }
    public event Action<T> ProgressReported;
    void IProgress<T>.Report(T data)
    {
        var action = ProgressReported;
        if (action != null)
        {
            context.Post(arg => action((T)arg), data);
        }
    }
}