2012-08-02 141 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