2013-07-11 73 views
1

在Visual C#/ .Net應用程序中,我必須讀取SerialPort,因此我將其分配給DataReceivedEventHandler。替代使用Control.Invoke

但是,我當然不能直接從處理程序中更改UI控件,因爲它們位於單獨的線程中。

該解決方案似乎是使用Control.Invoke,但是,我有太多的UI操作來執行,所以我擔心也許我沒有走正確的道路。

我應該做以下哪一項?

  • 選項A:與調用堅持無論如何,並且執行每個上的每個使用調用爲每個的各種控制的動作。選項B:放置一個50ms重複計時器,其中每50ms檢查一次布爾值是否爲DataReceived == true,如果是,則相應地更新UI控件。 (每次我讀取串行端口DataReceivedEventHandler中的數據時DataReceived設置爲true,否則爲false)。

  • 選項C:任何其他選項?

UPDATE:

成功具有以下(根據@ tcarvin答案,並@Hans帕桑特的評論)。

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{ 
    if (this.InvokeRequired()) 
    { 
     this.BeginInvoke(new EventHandler<SerialDataReceivedEventArgs>(DataReceivedHandler), new object[] { sender, e }); 
     return; 
    } 

    tbSerialStatus.Text = "Received text";  
} 
+1

只需努力緩衝您收到的數據。經常調用沒有太大意義,你只需要保持人眼快樂。無論如何,做這件事通常都是有問題的,它會導致UI線程獲取太多調用請求並停止繪畫的問題。 –

回答

3

我想你已經在想這個了。假設你在一個表單中編碼,這樣的事情應該工作。這是從臀部,你可能需要調整它一點:

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{ 

    if (this.InvokeRequired) 
    { 
     this.Invoke(new EventHandler<SerialDataReceivedEventArgs>(DataReceivedHandler), sender, e); 
     return; 
    } 

    // everything here runs on the UI thread, do what you like, 
    // and update as many UI controls as you like. 

} 

正如你所看到的,你不必包裝在一個單獨的Control.Invoke每個控制訪問。

+0

啊,所以每個控件不需要單獨調用!但爲什麼它是'Control.Invoke',不應該是'this.Invoke'?另外,爲什麼你將'DataReceivedHandler'指定爲委託 - 我們已經在該處理程序中,所以不應該改爲在UI線程上使用方法?我知道你只是寫了這個草案,但我試圖確定。 – boardbite

+0

這是一個麻煩的答案。不要像那樣使用Control.BeginInvoke。它是一種財產,而不是一種方法,它總是會成爲真實的。 *永遠不會*使用Control.Invoke(),它是死鎖的主要來源。特別是在DataReceived事件處理程序中,在程序退出時在UI線程上調用SerialPort.Close()方法對死鎖具有很高的可能性。始終使用BeginInvoke()代替。 –

+0

問題解決了 - 謝謝你們倆! (請參閱我的問題上的工作代碼UPDATE。) – boardbite

0

已解決。此方法的工作原理如下:

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{ 
    if (this.InvokeRequired()) 
    { 
     this.BeginInvoke(new EventHandler<SerialDataReceivedEventArgs>(DataReceivedHandler), new object[] { sender, e }); 
     return; 
    } 

    tbSerialStatus.Text = "Received text";  
}