0

我们在 .NET 4.0 中是否有机会等待响应然后返回响应?

目前我正在这样做,但它不是很好,我不喜欢它:

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 管理器类(我必须在单独的类(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。有任何想法吗?

4

3 回答 3

3

如果您不想异步读取,则使用 DataReceived 事件是没有意义的。只需在 GetResponse() 中直接调用 Read() 方法即可。

注意你不能假设你会得到一个完整的响应,你不能忽略 Read() 的返回值。它通常只返回几个字节,串行端口非常慢。所以一定要继续调用 Read() 直到你得到整个响应。

于 2012-08-02T16:54:35.857 回答
2

干净的方法是等待AutoResetEvent和等待接收回调发出信号。

通过使用此方法创建包装器,您可以有效地await在每个版本的 .Net 中。

于 2012-08-02T16:46:16.277 回答
2

对于您最初的问题,要阻止执行线程,您可以使用ManualResetEventAutoResetEvent,这将Set在您获得响应时获得。页面上有一个相当好的解释。

对于线程,经验法则是,如果您不是非常清楚自己在做什么,请不要这样做。

当您可以访问事件时同步阻塞似乎是一种浪费。考虑到数据是一个流,这可能最终难以维护抽象。

这里有一个例子对上述想法有更长的解释。

您也可以与TaskCompletionSource. 您可以调用而不是 set ,SetResult然后等待.Task,但想法几乎相同。

于 2012-08-02T16:47:52.467 回答