简体   繁体   中英

Updating Listbox in the background WPF

I am trying to make a hyper-terminal like program and i am having trouble getting the serial port to get a line and post it in the list box in the background. In the example below it will freeze the whole program while the the for loop runs 100 times and then spit out all 100 lines... i want it to update line by line and i am not sure why its doing it.

I also tried backgroundworker but it seemed to do the same thing.

Thanks in advance...

    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);
        }

    }

You are running your SP.ReadLine code in the UI thread.

I've split your code into three methods instead of one big splat of code.

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);
    }
}

In this clarified version, there are three methods

  1. Kickoff , which creates and runs the new thread
  2. ScheduleWork , which runs on _thread and schedules filling
  3. Fill , which actually performs the work you intended to run on _thread

The problem is that Kickoff runs on the UI thread, ScheduleWork runs on _thread , and Fill runs on the UI thread.

Dispatcher.BeginInvoke essentially means "take this method and run it on the UI thread whenever you feel like scheduling it, kthxbai." So your code all runs on the UI thread .

You need to do something like the following

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);
    }
}

I think what's going on is that your thread is taking priority over the GUI thread. You have to sleep the thread so the GUI can update or it will just queue up a bunch of updates and then process that queue when the event is over and the program sits idle. Setting it to a lower priority probably isn't a great way to do it.

Personally, I would move the COM port logic into an object and have that work on its own thread. Then you could poll that object's properties on a timer to see if any data was ready to be read.

You cannot update the UI from a background thread. Try changing the line dowing this to

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

try playing with the MSDN: DispatcherPriority to change the priority of your thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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