2012-04-12 107 views
0

嗯,我一直在C#中使用此SerialPort控件在過去的4天中苦苦掙扎,沒有令人滿意的結果。讓我解釋一下:串行端口異步讀取(非阻塞)+線程

我有一個與ac#prog通信的設備(Arduino UNO板卡),它模擬一個規模(簡單的請求/響應模式),設備發送一個由3個字節組成的命令序列):CHR(27)+ P + CHR(13),所以模擬器用一個模擬重量進行響應(我已經理清了設備如何捕獲並解析這個重量,所以這不再是問題)。 使用DataReceive事件似乎我使用Serialport.Read()丟失數據,所以我浪費了這種方法到目前爲止。 模擬器必須始終傾聽所述seq。的字節和必須有一個GUI。我明白爲此我必須使用一個線程爲了防止GUI被鎖定(可能是後臺工作?)和一種在(現在)這2個線程之間共享的緩衝區,並且防止線程同時讀/寫到緩衝區(我是否需要一個狀態機?)(我要求這方面的幫助,因爲我不知道這是一個好方法,還是我的假設是錯誤的,或者如果這是更簡單的方法來解決這個問題),所以我尋求建議和(運氣很好)代碼片段,或者如果您需要開發類似的應用程序,您是如何解決它的。

如果需要進一步闡明,我可以提供我迄今爲止所做的代碼。希望你可以對此有所瞭解。

在此先感謝。

UPDATE 1


這是代碼我迄今爲止:

ConcurrentQueue<byte> queue = new ConcurrentQueue<byte>(); 
.... 
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    bool listening = true; 
    while(listening) 
    { 
    if(serialPort.BytesToRead > 0) 
    { 
     byte b = (byte)serialPort.ReadByte(); 
     queue.Enqueue(b); 
    } 
    } 
} 

如此以來,一個命令具有字符13來結束(CR在ASCII):

public string GetCommand() 
{ 
    string ret = ""; 
    byte[] ba = new byte[1]; 
    byte b = (byte)' '; 

    while(b!=13) 
    { 
     if(queue.TryDequeue(out b)) 
     { 
      ba[0] = b; 
      ret += ASCIIEncoding.ASCII.GetString([ba]); 
     } 
    } 
    return ret; 
} 

爲了測試這個GetCommand()方法,我從buton_click事件中的主UI線程調用它,但它掛起了應用程序,do我需要創建另一個線程來調用GetCommand()?

+0

我更新了我的問題。我嘗試了什麼hitechrider,但我再次卡住,似乎線程是一個相當複雜的主題。 – favner85 2012-04-12 19:20:25

回答

1

請參閱this answer瞭解如何實現發送端。

對於讀取端使用專用線程,在該線程中從端口讀取消息,將其排列在合適的併發數據結構(例如ConcurrentQueue)中並立即循環以等待來自串行的下一個輸入港口。

從單獨線程上的隊列中獲取輸入。

可能有更有效的方法,但這個很容易實現和萬無一失。

2

對於少量數據這是可以的。但是如果數據比較大,就像傳遞一些http信息一樣,那麼隊列大小可能不夠。所以我認爲你應該使用非阻塞類型的體系結構。