的SerialPort触发DataReceived事件检索后关闭 [英] SerialPort fires DataReceived event after close

查看:188
本文介绍了的SerialPort触发DataReceived事件检索后关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到一个奇怪的现象,而试图阻止的SerialPort:该DataReceived事件检索继续火退订后,并呼吁在关闭! (见 StopStreaming 在以下code)。其结果是,在我的事件处理程序code我得到了端口关闭的消息一个InvalidOperationException。

I'm experiencing a weird behavior while trying to stop a SerialPort: the DataReceived event continues to fire after unsubscribing and after calling close! (see StopStreaming in the following code). As a result, in my event handler code I get an InvalidOperationException with the message that "The port is closed".

我在想什么?什么是关闭端口,停止活动的正确方法?

What am I missing? What is the correct way to close the port and stop the events?

编辑:每次我跑我的code时候,我得到这个错误。因此,这是不是一场比赛条件随机发生,而是一个系统性的问题,表示完全打破code!不过,我看不出...

I get this error every time I run my code. So this is not a race condition that happens randomly but rather a systematic problem indicating a completely broken code! However, I fail to see how...

private SerialPort comPort = new SerialPort();

public override void StartStreaming()
{
  comPort.Open();
  comPort.DiscardInBuffer();
  comPort.DataReceived += comPort_DataReceived;
}

public override void StopStreaming()
{
  comPort.DataReceived -= comPort_DataReceived;
  comPort.Close();
  isStreaming = false;
}

private void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
  if (e.EventType == SerialData.Chars)
  {
    SerialPort port = (SerialPort)sender;
    int N = comPort.BytesToRead;
    for (; N > 0; N--)
    {
      byte b = Convert.ToByte(comPort.ReadByte());
      //... process b
    }
  }
}

编辑:下面的建议,我改变了 StopStreaming code到这样的事情:

following the suggestions, I changed StopStreaming code to something like this:

public override void StopStreaming()
{
  comPort.DataReceived -= comPort_DataReceived;
  Thread.Sleep(1000);
  comPort.DiscardInBuffer();
  Thread.Sleep(1000);
  comPort.Close();
  isStreaming = false;
}

这似乎是现在的工作,但我真的不愉快的心情。我希望有一种更有效的方法,以消除回调而不是在程序中插入睡眠周期。

It seems to work now but I'm not really that happy. I wish there was a more effective way to remove the callback rather than inserting sleep periods in the program.

推荐答案

您DataReceived事件检索处理程序被调用一个线程池线程。是的,他们已经得到了在一个没有predictable时间运行您的code的尴尬习惯,它不是瞬间。所以这是非常必然的,如果该设备正在发送数据时,它可以与你的亲密()调用种族和运行的的你关闭它。退订仍不能解决问题,线程池线程已经得到了它的目标的方法。

Your DataReceived event handler is called on a threadpool thread. And yes, they've got the awkward habit of running your code at an unpredictable time, it is not instant. So it is fairly inevitable that, if the device is actively sending data, that it can race with your Close() call and run after you closed it. Unsubscribing doesn't fix it, the threadpool thread already got its target method.

你知道你在做什么来触发此问题,正在关闭的端口的,而的设备发送数据。这不是很大,它保证会导致数据丢失。但不是不可能的,当你在调试code,因为你实际上并不关心数据的情况发生。

Do realize what you are doing to trigger this problem, you are closing the port while the device is sending data. That's not great, it is guaranteed to cause data loss. But not unlikely to happen when you are debugging your code since you don't actually care about the data.

一个应对措施是关闭握手因此该设备不能再发送任何东西。丢弃输入缓冲器。然后睡了一会,一两秒钟,以确保在飞行的任何线程池线程完成运行。然后关闭端口。一个很实用的一种是根本就没有关闭端口,Windows将照顾它,当你的进程终止。

A counter-measure is to turn off handshaking so the device cannot send anything anymore. Discard the input buffer. Then sleep for a while, a second or two, to ensure that any threadpool threads in-flight have completed running. Then close the port. A very pragmatic one is to simply not close the port, Windows will take care of it when your process terminates.

这篇关于的SerialPort触发DataReceived事件检索后关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆