c#串口接收事件:当我关闭端口并从Port.DataReceived中删除事件时,程序仍在分支接收事件

时间:2014-07-19 07:13:35

标签: c# events serial-port

我想禁用/启用接收而不关闭端口或删除接收处理程序方法,因为它们不起作用或我做错了什么。

我现在在做;

byte[] rData = new byte[10];
public void SendData(byte[] a, int count)
{
    if (Port.IsOpen == false)
        Port.Open();
    Port.Write(a, 0, count);
    // start receive timeout timer
    Port.DataReceived += new SerialDataReceivedEventHandler(ReceiveData);
}
public void ReceiveData(object s, SerialDataReceivedEventArgs e)
{
    int ctrl = 0;
    int DataCnt = 5; // for example
    Port = (SerialPort)s;
    ctrl = Port.Read(rData, 0, DataCnt); // if timeout haven't finished yet
    if (ctrl != DataCnt)
    { /* set receive error flag */ }
    else
    {
        Port.DiscardInBuffer();
        if (Port.IsOpen == true)
            Port.Close();
        Port.DataReceived -= new SerialDataReceivedEventHandler(ReceiveData);
        // set receive complete flag
    }
}

我正确获取字节,但是当程序分支else的{​​{1}}块时,我将丢弃输入缓冲区,如果端口打开则关闭端口,并删除接收事件但是它在ReceiveData中再次分支并且自然ReceiveData事件正在发生,因为我已经关闭了端口。从InvalidOperationException删除事件后,为什么程序再次分支接收事件?我正在使用Windows 8.1专业版和Visual Studio 2010专业版。谢谢。

1 个答案:

答案 0 :(得分:0)

我的建议是不要搞乱数据接收事件处理程序中的端口。在调用处理程序之后你不知道端口做了什么(或者订阅同一事件的其他事件处理程序可能做什么),并且当你返回时它可能不会被关闭,这可能导致"未定义的行为& #34;

相反,设置一个标志以指示您已收到所有数据并准备关闭端口,并让您的主程序循环在将来的某个时刻实际关闭它。 (一旦获得所需信息,您也可以忽略对数据接收事件处理程序的任何额外调用)

取消订阅事件处理程序后,如果另一个线程在您取消订阅时正在调用处理程序,您仍然可以调用处理程序。因此,为了避免竞争条件,最好是优雅地处理额外的调用,而不是在事件处理期间依赖取消订阅。这不太可能,但涉及线程的时候,"不太可能"通常经常发生!

要记住事件处理程序的一个好的经验法则是在处理事件时尽可能少地完成工作。记录您需要知道的内容并将所有其他处理推迟到另一个线程,以便您可以快速返回给调用者。