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

时间:2013-03-14 14:37:59

标签: c# multithreading user-interface udp

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

所以我的问题是,在不阻塞GUI线程的情况下,监听UDP消息并将内容写入GUI的最佳做法是什么?

1 个答案:

答案 0 :(得分:1)

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

之后,您只需要更新UI的一些方法。还有几种方法可以实现(有些是特定于你正在使用的UI功能(WPF,winform等),有些则不是。

使用IProgress<T>特别有用,特别是因为它不依赖于特定的UI技术。在UI中创建Progress对象,并指定在获得特定结果时如何更新UI,将对象传递给后台工作程序,并在收到信息时使其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);
        }
    }
}