2012-08-02 140 views
0

我們是否已經在.NET 4.0中有機會等待響應,然後返回響應?SerialPort等待響應

目前我正在做這樣的,但它是不是真的很好,我不喜歡它:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     byte[] options = new byte[]{1,1,0}; 
     COMManager mgr = new COMManager("COM1"); 

     byte[] result = mgr.GetResponse(options); 
    } 
} 

我的COM Manager類 (我必須做在一個單獨的操作(dll)):

public class COMManager 
    { 
     SerialPort sp = null; 
     byte[] result = null; 
     bool completed = false; 

     public COMManager(string comport) 
     { 
      sp = new SerialPort(comport); 
      sp.DataReceived +=new SerialDataReceivedEventHandler(sp_DataReceived); 
     } 

     public byte[] GetResponse(byte[] option) 
     { 
      sp.Write(option, 0, option.Length); 
      //I don't like the way... 
      while (!completed) { } 
      completed = false; 
      return result; 
     } 

     void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) 
     { 
      result = new byte[sp.BytesToRead]; 
      sp.Read(result, 0, sp.BytesToRead); 
      completed = true; 
     } 
    } 

在.NET 4.5中,我們可能有機會使用「await」語句。但是對於當前的項目,我們只允許使用.NET 4.0。 任何想法?

回答

1

對於你原來的問題,要阻止正在執行的線程,你可以使用一個ManualResetEventAutoResetEvent,當你的響應已經獲得時,將得到Set。在頁面上有一個相當好的解釋。

對於線程,經驗法則是,如果您對所做的事情不是非常清楚,請不要這樣做。

注意: 當你有權訪問事件時同步阻塞看起來很浪費。考慮到數據是一個流,這可能最終難以保持抽象。

+0

嗨阿斯蒂。感謝您的回覆。我以前從未使用過ManualResetEvents。所以我添加「私人靜態ManualResetEvent mre =新的ManualResetEvent(false);」到我的COMManager類和「mre.Reset()」將取代我的while循環。並在dp_DataReceived而不是完成= true我設置mre.Set()正確? – user1011394 2012-08-02 16:55:13

+0

@ user1011394是的,基本上。不要聲明它是靜態的。 – Asti 2012-08-02 17:08:29

+0

您也可以使用AutoResetEvent,它在設置後會自動重置,所以如果您願意,您不必重設Reset。 – Asti 2012-08-02 17:10:32

2

乾淨的方法是等待一個AutoResetEvent並等待接收回調來發信號。

通過使用此方法創建包裝,您可以在每個.Net版本中有效地使用await

2

如果您不想異步讀取,使用DataReceived事件沒有意義。只需在GetResponse()中直接調用Read()方法即可。

請注意,您不能假設您將得到完整的響應,您不能忽略Read()的返回值。它通常只返回幾個字節,串口很慢。所以一定要保持調用Read(),直到獲得完整的響應。

+0

嗨Hans Passant,這是一個異步調用。首先,我必須寫字節(發送給設備),其次,設備將解釋它併發送給我一個單獨的響應。 – user1011394 2012-08-02 16:59:17