SerialPort等待响应

时间:2012-08-02 16:41:32

标签: c# port

我们在.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。 有什么想法吗?

3 个答案:

答案 0 :(得分:3)

如果您不想异步读取,那么使用DataReceived事件毫无意义。只需在GetResponse()中直接调用Read()方法。

请注意,您不能假设您将获得完整的响应,您不能忽略Read()的返回值。它通常只返回几个字节,串口很慢。因此,请务必继续调用Read()直到获得完整的响应。

答案 1 :(得分:2)

干净的方法是等待AutoResetEvent并接收回叫信号。

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

答案 2 :(得分:2)

对于您的原始问题,要阻止正在执行的主题,您可以使用ManualResetEventAutoResetEvent,当获得您的回复时,Set将获得TaskCompletionSource。页面上有一个相当不错的解释。

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

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

通过here上的示例,对上述想法有更长的解释。

您也可以与SetResult异步执行此操作。您可以拨打.Task而不是设置,等待{{1}},但这个想法几乎相同。