Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# c串口接收事件:当我关闭端口并从port.DataReceived中删除事件时,程序仍在对接收事件进行分支_C#_Events_Serial Port - Fatal编程技术网

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

C# c串口接收事件:当我关闭端口并从port.DataReceived中删除事件时,程序仍在对接收事件进行分支,c#,events,serial-port,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.Data

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

我现在正在做

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
    }
}

我得到的字节是正确的,但当程序将ReceiveData的else块分支时,我会丢弃输入缓冲区,关闭打开的端口,删除接收事件处理程序,但它再次在ReceiveData中分支,并且由于我关闭了端口,自然会发生InvalidOperationException事件。为什么程序在从Port.DataReceived删除事件后再次分支接收事件?我正在使用Windows 8.1 pro和visual studio 2010 pro。谢谢。

我的建议是不要弄乱数据接收事件处理程序中的端口。您不知道调用处理程序后端口会做什么,也不知道订阅同一事件的其他事件处理程序会做什么,并且在返回时它可能不会被关闭,这可能会导致未定义的行为

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

取消订阅事件处理程序后,如果您取消订阅时另一个线程正在调用处理程序,您仍然可以获得对处理程序的调用。因此,为了避免竞争条件,在事件处理过程中,最好优雅地处理额外的呼叫,而不是依赖取消订阅。这是不可能的,但就线程而言,不可能的情况经常发生


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

您是否尝试在关闭端口之前取消订阅?谢谢@DmitryDovgopoly您的意思是;Port.DataReceived-=新的SerialDataReceivedEventHandlerReceiveData;港口关闭前?如果你是说是的,我已经试过了,但仍然是一样的,这段代码中有太多的bug,无法猜测会发生什么。从MSDN或google查询中的现有代码片段中找到正确的方法。我找到了关于前5个串行端口提示的链接,并讨论了在第3个提示中关闭端口,但在此或端口下无法使用Invoke或BeginInvoke方法。谢谢@HansPassant。但是我不明白为什么我的代码中有太多的bug。我删除了端口=串行端口;如果Port.IsOpen==true{Port.Close}并添加Form.CheckForIllegalCrossThreadCalls=false;低于int-DataCnt=0时;和Form.CheckForIllegalCrossThreadCalls=true;在ReceiveData事件的底部,它的工作状态为true,并且在从处理程序取消订阅事件后不会分支到事件。但这是真的吗?我不知道。谢谢@Jason Williams我也删除了端口关闭方法,但取消订阅程序仍在处理程序中,但我在上面的评论中对处理程序做了一些更改。我真的不想打开或关闭端口我的程序的任何状态只是想启用/禁用Rx或Tx,但SerialPort类中没有关于这一点的属性或方法,我也不想用C进入低级。我会尝试你的建议,但现在我需要在pc和我设计的嵌入式设备之间进行测试通信。通信正常后,我将更改我电脑程序的一些状态。谢谢。请澄清一下,要停止接收/发送,必须关闭端口。