在C#中,检查后台线程的更改最有效的方法是什么?

5

我为每个网络通信创建一个线程,在它们从客户端那里收到响应后,将响应添加到列表中。我在执行下面的任务以启动它,以查看是否有通信进来。它会在屏幕上显示最近的通信。

Task task = new Task(
(() =>
 {
    int i = 0;
    while (true)
    {
        if (responses.Count > i){
            Debug.WriteLine(responses[i]);
            int index = Form.ActiveForm.Controls.IndexOfKey("responseBox");
            Form.ActiveForm.Invoke((MethodInvoker) (() => Form.ActiveForm.Controls[index].Visible = true));
            Form.ActiveForm.Invoke((MethodInvoker) (() => Form.ActiveForm.Controls[index].Text = responses[i]));
            i++;
        }
    }
 }));
task.Start();

我的问题是:有没有更好的方法来做到这一点?让任务不断地为很少发生的事情而工作,这似乎是错误的。
编辑:我对C#非常陌生,如果有明显的问题,请不要犹豫指出。
更新:
根据sidewinder提供的MS的漂亮教程,我在List的Add函数中添加了一个简单的事件,如下所示:
public delegate void ChangedEventHandler(object sender, EventArgs e);

public class listWithChanges<T> : List<T> 
{
    public event ChangedEventHandler Changed;

    protected virtual void OnChanged(EventArgs e)
    {
        if (Changed != null)
            Changed(this, e);
    }

    public new void Add (T item)
    {
        base.Add(item);
        OnChanged(EventArgs.Empty);
    }
}

并通过委托添加到我的输出中

responses.Changed += ((o, e) => {
                                int index = Form.ActiveForm.Controls.IndexOfKey("responseBox");
                                Form.ActiveForm.Invoke((MethodInvoker) (() => Form.ActiveForm.Controls[index].Visible = true));
                                Form.ActiveForm.Invoke((MethodInvoker) (() => Form.ActiveForm.Controls[index].Text = responses[responses.Count - 1]));
                              });

2
为什么不直接触发事件呢? - Daniel A. White
2
因为我是c#的新手,不知道你的意思 :) - Damien
1
事件是在C#中处理此类操作的最佳方式,如果您需要入门教程,这里提供了微软官方的教程链接:https://msdn.microsoft.com/zh-cn/library/aa645739(v=vs.71).aspx - Irwene
1
这似乎不是一个很好的后台工作程序。看起来更适合在主线程上使用定时器或者在responses有新项时触发事件。 - LarsTech
请问大家,当事件被一个不同于发出事件的线程接收时,事件将如何运作? - Mike Nakis
显示剩余8条评论
2个回答

4

事件将是一个不错的解决方案。

事件是观察者模式的一种实现,在该模式中,源(网络通信)会通知其观察者(在您的示例中调用任务的任何人)发生了某些事情。

它更加高效,因为它不会浪费CPU使用率在无限循环中,该方法仅在客户端响应时执行。

C#对事件有很好的支持,请考虑阅读MS教程(由Sidewinder94最初发布)。


2
如果您不想对代码进行大量重构,可以为responses集合使用阻塞队列,这样您的读取线程在等待队列中出现项目时会被阻塞。
在阻塞队列中等待某些东西不会消耗CPU。 (从技术上讲不是零,但仍然不可察觉。)
快速搜索可得到此内容:MSDN-BlockingCollection Class

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接