2013-07-25 174 views
0

假設我想從串口接收一些數據。使用serial.ReadLine()的塊調用並使用以下事件。多線程和偵聽串行端口

private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) 
{ 
     var port = (SerialPort)sender; 

     string line = port.ReadLine(); 

      // PROCESS DATA Somewhere else 

}

我是從不同的源讀取和所有他們的說,serial.ReadLine都有自己的線程,我不應該從這個線程,除非使用的BeginInvoke修改UI。但是,我注意到,在一段時間內,用戶界面將無法響應。

所以這是我的問題。調用port_DataReceived中的新線程將是一個壞主意? 我想接收數據並在另一個線程中處理接收到的數據,但是mythread.Start()放在哪裏?我不能一直開始它,我只是想讓它知道何時在收到數據後獨立運行。根據MSDN,中止的線程不能再次啓動。把Thread.Sleep凍結我的用戶界面。

回答

2

你誤會發生了什麼事情。 SerialPort.ReadLine()做不是使用線程。它是在另一個線程上運行的DataReceived事件處理程序。必要的,以便SerialPort可以儘快通知您的代碼有關收到的數據,而無需等待您的UI線程閒置。這確實意味着你不能直接從你的事件處理程序更新你的UI,無論如何你會得到一個InvalidOperationException。

DataReceived事件當然可以幫助您避免凍結您的UI。你的問題中提示太少,不知道你真正的問題可能是什麼。有一個問題可能是經常使用Control.BeginInvoke(),用調用請求氾濫UI線程,因此它不會執行常規任務。就像迴應輸入和繪畫一樣。解決這個問題的方法是簡單地調用次數少一些,你只需要讓人類的眼睛快樂起來,而且不會那麼快。緩衝接收到的數據,保持輸出到您的UI的合理數量,這樣人們實際上可以看到的不僅僅是模糊。

另一個常見問題是死鎖,它會永久凍結你的程序。使用調試器很容易診斷,您會看到程序停留在SerialPort.Close()調用中。當您使用Control.Invoke()而不是Control.BeginInvoke()時會發生這種情況。不要使用Invoke()。

+0

然後,這意味着我不能調用DataRecieved內的其他函數來更新我的UI。此外,我不能每次收到一條消息時都做Thread.Start(),那我該怎麼辦? – SpcCode

+1

@Hans已經很清楚地解釋了,這就是我給他+1的原因。與「多線程」中的許多答案不同,他只是在點對點。不要使用Invoke()。不要過度開始使用Windows消息調用GUI並將其輸入隊列。不要連續創建/開始/終止/銷燬線程。如果您絕對需要處理另一個線程中的串行數據,請使用BlockingCollection隊列將數據排隊。 –