2012-11-02 63 views
1

我正在嘗試製作一個超級終端程序,並且無法獲取串行端口並將其發佈到後臺的列表框中。在下面的例子中,它會凍結整個程序,而for循環運行100次,然後吐出所有100行......我希望它逐行更新,我不知道爲什麼它會這樣做。在後臺更新列表框WPF

我也試過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); 
     } 

    } 
+0

和正常工作。與你當前的代碼你持有的BeginInvoke爲100線。你需要100個BeginInvoke。 – Paparazzi

回答

0

我認爲,這是怎麼回事是你的線程在GUI線程的優先級更高。您必須睡眠該線程,以便GUI可以更新,或者只需排隊一堆更新,然後在事件結束並且程序閒置時處理該隊列。將它設置爲較低的優先級可能不是一個好方法。

就我個人而言,我會將COM端口邏輯移動到一個對象中,並使其在自己的線程上工作。然後,您可以在定時器上輪詢該對象的屬性以查看是否有數據準備好被讀取。

0

您無法從後臺線程更新UI。嘗試改變線dowing這

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

嘗試與MSDN: DispatcherPriority打更改線程的優先級。

1

您正在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. 填寫,實際執行您打算在運行工作

的問題是,開球運行在UI線程上,ScheduleWork運行在_thread,並填寫在UI線程上運行

Dispatcher.BeginInvoke基本上是指「採取這種方法,每當你感覺計劃任務,kthxbai在UI線程上運行它。」所以,你的代碼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); 
    } 
} 
我已經使用BackGroudWorker ReportProgress對於這樣的東西