2013-05-02 41 views
0

我不知道這是一個很好的方式來處理這個任務的堆棧,但我敢肯定有一個更快的方法... 我從我的微控制器獲取數據,但數據長度並不總是相同的長度。 我想也許我可以推送數據在我的堆棧和一個線程中,我可以彈出它並解碼消息。我沒有想要減慢DataReceivedHandler的速度,所以我創建了一個Thread,它可以在我的decodeMessage()函數中彈出數據並將其寫入我的Listview。串口讀取+線程還是更好的?

很短的時間,我收到了System.OutOfMemories異常後..

任何想法我怎麼能以更好的方式做到這一點?

我從我的串口讀取只是當數據到達這裏:

Stack<byte[]> stack = new Stack<byte[]>(); 

.....

public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort sp = (SerialPort)sender; 
    byte[] data = new byte[sp.BytesToRead]; 
    sp.Read(data, 0, data.Length); 

    stack.Push(data); 
} 

這是我的主題:

private void formatData() 
{ 
    try 
    { 
     while (true) 
     { 
      byte[] data; 
      int i=0; 

      Dispatcher.BeginInvoke(new Action(() => 
      { 
       while (stack.Count > 0) 
       { 
        data = stack.Pop(); 
        while (i < data.Length) 
        { 
         decodeMessage(data[i]); 
         i++; 
        } 
       } 
      }));   
     } 
    } 
    catch (Exception ex) 
    { 
     System.Windows.Forms.MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
    } 
} 

thx

+0

看來你需要[BlockingCollection(http://msdn.microsoft.com/en-us/library/dd267312.aspx),而不是'Stack' – I4V 2013-05-02 10:32:44

+6

我不認爲堆棧是你想要,隊列可能更適合這個,因爲它是FIFO。如上所述,BlockingCollection默認使用隊列,並且是線程安全的。你的堆棧實現不是線程安全的,這可能會導致你的問題。 – 2013-05-02 10:34:29

+0

但是我怎麼知道,我應該通過Queue讀多少個元素? – user2261524 2013-05-02 10:40:21

回答

3

此代碼使用線程安全隊列。我簡化了一些我自己的代碼,所以這段代碼沒有經過測試或編譯。如果您在編譯時遇到問題或者產生錯誤,請向我添加評論,我會幫您解決。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO.Ports; 
using System.Windows.Threading; 
using System.Collections.Concurrent; 

void someRoutine() 
{ 
    // initialize queue before using it 
    serialDataQueue = new ConcurrentQueue<char>(); 

} 


/// <summary> 
/// data from serialPort is added to the queue as individual chars, 
/// a struct may be better 
/// </summary> 
public ConcurrentQueue<char> serialDataQueue; 

// get data 
void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort sp = sender as SerialPort; 
    int bytesAvailable = sp.BytesToRead; 

    // array to store the available data  
    char[] recBuf = new char[bytesAvailable]; 

    try 
    {  
     // get the data 
     sp.Read(recBuf, 0, bytesAvailable); 

     // put data, char by char into a threadsafe FIFO queue 
     // a better aproach maybe is putting the data in a struct and enque the struct   
     for (int index = 0; index < bytesAvailable; index++) 
      serialDataQueue.Enqueue(recBuf[index]); 

    } 
    catch (TimeoutException ex) 
    { 
     // handle exeption here 
    } 
} 



/// <summary> 
/// Check queue that contains serial data, call this 
/// routine at intervals using a timer or button click 
/// or raise an event when data is received 
/// </summary> 
private void readSearialDataQueue() 
{ 
    char ch; 

    try 
    { 
     while (serialDataQueue.TryDequeue(out ch)) 
     { 
      // do something with ch, add it to a textbox 
      // for example to see that it actually works 
      textboxDataReceived.Text += ch; 
     } 

    } 
    catch (Exception ex) 
    { 
     // handle ex here 
    } 
}