多个线程向ListBox添加和移除项目

3

我有以下代码,在其他应用程序中运行良好。

在我的应用程序中,有4个线程每60毫秒调用AddToList方法。

一旦列表中达到1000个项目并开始尝试删除项目,则CPU使用率会达到100%。将计数设置为100会解决此问题。

有任何想法吗?

以下是代码:

public delegate void dgAddToList(string Message, int InputID);

public void AddToList(string Message, int InputID)
{
   if (this.InvokeRequired)
   {
      this.BeginInvoke(new dgAddToList(AddToList), new object[] { Message, InputID });
   }
   else
   {

      switch (InputID)
      {
         case 0:
            this.listBox1.Items.Insert(0, Message);

            if (this.listBox1.Items.Count > 100) 
            this.listBox1.Items.RemoveAt(this.listBox1.Items.Count - 1);

            break;

         case 1:
             this.listBox2.Items.Insert(0, Message);

             if (this.listBox2.Items.Count > 100) 
                this.listBox2.Items.RemoveAt(this.listBox2.Items.Count - 1);

             break;

          case 2:
              this.listBox3.Items.Insert(0, Message);

              if (this.listBox3.Items.Count > 100) 
                this.listBox3.Items.RemoveAt(this.listBox3.Items.Count - 1);

               break;

           case 3:
              this.listBox4.Items.Insert(0, Message);

              if (this.listBox4.Items.Count > 100) 
                 this.listBox4.Items.RemoveAt(this.listBox4.Items.Count - 1);

               break;
     }
}

更新: 仅为澄清,第一个线程将仅更新Listbox1,第二个线程将更新Listbox2。这是由InputID参数决定的,因此Thread1传递0,Thread 2传递1。


你是说你从多个线程调用那段代码?该代码本身不是线程安全的,你检查计数然后调用remove(另一个线程可能同时添加/删除了一些内容)?但这并不是性能问题的根源。 - Anders Forsgren
@Anders这里进行了序列化调用。线程安全不是问题。 - David Heffernan
啊,我明白了。那么线程数量真的是一个问题吗?如果一个线程以1/4的间隔时间运行,您不会得到相同的性能吗? - Anders Forsgren
这是在Winforms项目中使用的,多个线程正在调用该方法。 - Jon
@jon 调用确实使其线程安全,因为这些方法都在同一个线程上运行。 - David Heffernan
显示剩余7条评论
1个回答

1

我认为60毫秒和4个异步线程对于UI消息管道来说是一个很大的负载,因此它被卡住了。如果这符合应用程序行为要求的角度,请尝试增加时间间隔(例如200毫秒)。

顺便说一句,您可以像下面所示重新构建switch语句,这样代码会更清晰:

public void AddToList(string Message, int InputID)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke(new dgAddToList(AddToList), new object[] { Message, InputID });
    }
    else
    {
        ListBox listBoxInstance = null;

        switch (InputID)
        {
            case 0:
                listBoxInstance = this.listBox1;
                break;
            case 1:
                listBoxInstance = this.listBox2;
                break;
            case 2:
                listBoxInstance = this.listBox3;
                break;
            case 3:
                listBoxInstance = this.listBox4;
                break;
        }

        if (listBoxInstance != null)
        {
             listBoxInstance.Items.Insert(0, Message);
             if (listBoxInstance.Items.Count > 100)
             {
                listBoxInstance.Items.RemoveAt(
                                  listBoxInstance.Items.Count - 1);
             }
        }
    }
}

@Jon:基本上你是在列表的开头添加一个新消息,然后删除最后一项?顺便问一下,你使用的控件类型是什么?能否给出包括命名空间在内的完整名称? - sll
@Jon:不,它只在单独的线程中调用委托,但它并不保证任何线程安全性。首先尝试使用简单的lock() - sll
1
@David Heffernan:我的错,我会撤回我的答案。感谢您指出这个问题。 - sll
@David Heffernan:OP说“4个线程调用AddToList”,因此这个.BeginInvoke()将不会从UI线程中调用,这是否意味着它也会向UI线程发送消息,因为它并非由UI线程运行? - sll
@sll 我不理解这个问题。 - David Heffernan
显示剩余8条评论

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