2016-11-16 64 views
1

我一直在使用SerialPort類在與我設計的一些外部硬件進行通信的應用程序中有一段時間。在所述硬件的調試過程中,我發現一些事情是不可靠的,最近我偶然發現了this這似乎是東西。如何更可靠地使用SerialPort類

我想落實到我的應用程序這一點,但是我對接收數據的兩個問題...

所以,我掛在文章中,筆者提到,DataReceived事件是有問題的,並顯示它是如何被使用的典型代碼示例...

port.DataReceived += port_DataReceived; 

// (later, in DataReceived event) 
try { 
    byte [] buffer = new byte[port.BytesToRead]; 
    port.Read(buffer, 0, buffer.Length); 
    raiseAppSerialDataEvent(buffer); 
} 
catch (IOException exc) { 
    handleAppSerialError(exc); 
} 

然後筆者認爲是顯示了正確的方法是什麼?

byte[] buffer = new byte[blockLimit]; 
Action kickoffRead = null; 

kickoffRead = delegate { 
port.BaseStream.BeginRead(buffer, 0, buffer.Length, 
     delegate (IAsyncResult ar) { 
      try { 
       int actualLength = port.BaseStream.EndRead(ar); 
       byte[] received = new byte[actualLength]; 
       Buffer.BlockCopy(buffer, 0, received, 0, actualLength); 
       raiseAppSerialDataEvent(received); 
      } 
      catch (IOException exc) { 
       handleAppSerialError(exc); 
      } 
      kickoffRead(); 
     }, null); 
    }; 
    kickoffRead(); 

我的問題圍繞着使用BaseStream.BeginRead;如果我的班級裏有關於這些數據的內容,應該把這些數據讀出來?我的第一個想法是在DataReceived事件中,如第一個示例所示,不應使用SerialPort類,作者提到代碼位於註釋中的DataReceived事件中,但對於示例,顯示作者沒有提及的更好方法在哪裏代碼應該是這樣我以爲他仍然指的是DataReceived事件,但後來作者提到DataReceived事件本身有問題,所以......?這裏的任何指導都會很棒,如果它很明顯的話,我們也可以採用appologies

如果我沒有提到任何有利於任何人試圖回答這個問題,那麼請通知我。 在此先感謝您的任何指導和/或反饋!

+0

對於程序員來說,一半的代碼是非常常見的,大喊「不可靠!」,這樣做使得它工作並將其聲明爲「優越」。 DataReceived中的標準錯誤是不關注e.EventType,即使您知道有字節要讀取並使用Read()而不使用其返回值,也可以使用BytesToRead。沒有爲ErrorReceived事件實現事件處理程序是慢性的,所以你不能說這些數據被損壞了。只問一個問題。 –

+0

您是否建議文章沒有任何真正的優點,或者我已經「半化」了代碼?如果是後者,那麼是的,我並不是指完成的項目,但即使是微軟自己也在MSDN上提到,DataReceived事件不會針對每個接收到的字節而提出,而這正是我正在經歷的。我鏈接的文章指出,SerialPort類沒有正確使用底層的Win32串口API,所以我只是嘗試了一些不同的實驗。 –

+0

@HansPassant:你是對的,忽略錯誤並不是一個好主意,但是'ErrorReceived'事件並不是一個好辦法,因爲錯誤情況下成功收到的數據會失序。 (我已經閱讀了源代碼,IOPSP代碼確實具有不可逾越的設計缺陷,這不僅僅基於實驗數據)您是否忽視了由'ReadAsync'返回的任務,我推薦也通過完成故障狀態? –

回答

2

這是一個遞歸函數,因此您只需在打開端口後調用此代碼,並且它會繼續重複自己而不會阻止執行(或需要DataReceived事件處理程序)。

+0

感謝您的回答,我已經對遞歸代碼做了一些閱讀,我想我和你在一起。我會在星期一做一些測試,然後我會用一個或兩個問題將其標記爲答案或評論;)再次感謝。 –

+0

我不知道誰低估了這一點,但穆爾斯是正確的(+1)。我應該知道,我是該博客的作者。 –

+0

另請注意,它不是* true *遞歸,'BeginRead'塊是從完成處理程序調用的,而不是從它本身調用的,所以調用堆棧不會無限增長。 –