繁体   English   中英

在后台WPF中更新列表框

[英]Updating Listbox in the background WPF

我正在尝试制作一个像程序一样的超级终端,但我在获取串行端口以获取线路并将其发布到后台的列表框中时遇到了麻烦。 在下面的示例中,它将使整个程序冻结,而for循环将运行100次,然后吐出全部100行...我希望它逐行更新,但我不确定为什么这样做。

我也尝试了backgroundworker,但它似乎做同样的事情。

提前致谢...

    static System.Threading.Thread thread;
    public void button2_Click(object sender, RoutedEventArgs e)
    {
        if(Sp.IsOpen){
            stop = false;

            thread = new System.Threading.Thread(
                new System.Threading.ThreadStart(
                  delegate()
                  {
                    System.Windows.Threading.DispatcherOperation
                      dispatcherOp = listBox1.Dispatcher.BeginInvoke(
                      System.Windows.Threading.DispatcherPriority.Normal,
                      new Action(
                        delegate()
                        {
                            for(int y = 0; y <100; y++)
                            {
                                String line = Sp.ReadLine();
                                listBox1.Items.Add(line);
                            }
                        }
                               ));

              }
          ));
            thread.Start();


        }else{
            item.Content = ("No Comm Ports are Open");
            item.IsSelected = true;
            listBox1.Items.Add(item);
        }

    }

您正在UI线程中运行SP.ReadLine代码。

我将您的代码分为三种方法,而不是一小段代码。

private Thread _thread;

private void Kickoff()
{
    _thread = new Thread(() => ScheduleWork(listBox1));
    thread.Start();
}

private void ScheduleWork(ListBox box)
{
    box.Dispatcher.BeginInvoke((Action)() => Fill(box));
}

private void Fill(ListBox box)
{                           
    for(int y = 0; y <100; y++)
    {
        String line = Sp.ReadLine();
        listBox1.Items.Add(line);
    }
}

在此澄清的版本中,有三种方法

  1. 启动 ,创建并运行新线程
  2. ScheduleWork ,它在_thread上运行并计划填充
  3. Fill ,实际上执行您打算在_thread上运行的工作

问题在于, 启动程序在UI线程上运行, ScheduleWork_thread_thread ,而Fill在UI线程上运行。

Dispatcher.BeginInvoke本质上是指“采用这种方法并在需要调度时在UI线程上运行它,kthxbai。” 因此,您的代码全部在UI线程上运行

您需要执行以下操作

private Thread _thread;

private void Kickoff()
{
    _thread = new Thread(() => ScheduleWork(listBox1));
    thread.Start();
}

private void ScheduleWork(ListBox box)
{                  
    for(int y = 0; y <100; y++)
    {
        String line = Sp.ReadLine();
        box.Dispatcher.BeginInvoke((Action<string>)(str) => 
            listBox1.Items.Add(str),
            line);
    }
}

我认为这是因为您的线程的优先级高于GUI线程。 您必须休眠线程,以便GUI可以更新,否则它将只是排队进行一系列更新,然后在事件结束且程序处于空闲状态时处理该队列。 将其设置为较低的优先级可能不是一个好方法。

就个人而言,我会将COM端口逻辑移到一个对象中,并在其自己的线程上进行工作。 然后,您可以在计时器上轮询该对象的属性,以查看是否已准备好读取任何数据。

您不能从后台线程更新UI。 尝试将行修改为

listBox1.Dispatcher.BeginInvoke(DispatcherPriority.Render, ()=>listBox1.Items.Add(line));

尝试使用MSDN:DispatcherPriority更改线程的优先级。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM