串口线程锁,同时处理从串口读取的数据

Jas*_*ith 1 c# multithreading asynchronous serial-port locks

我有一个事件处理程序,只要在串行端口上接收到数据,它就会被调用,一旦调用此事件,我就会处理单个字节的数据,直到处理完所有数据。

我的问题是,如何确保这个 IBSerialPort_DataReceived 事件处理程序在我第一次被调用时仍在处理字节时不会再次被异步调用,即我想保证 ProcessByte 方法只在一个线程上执行一次。

void IBSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
  while (BytesToRead > 0)
  {
    ProcessByte((byte)ReadByte());
  }
}
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 5

这已经在 SerialPort 类中互锁了。如果您的事件处理程序仍在运行,则有一个内部锁可确保 DataReceived 事件不会再次触发。

您可以在参考源中看到相关代码,我将在此处重现:

    private void CatchReceivedEvents(object src, SerialDataReceivedEventArgs e)
    {
        SerialDataReceivedEventHandler eventHandler = DataReceived;
        SerialStream stream = internalSerialStream;

        if ((eventHandler != null) && (stream != null)){
            lock (stream) {
                // SerialStream might be closed between the time the event runner
                // pumped this event and the time the threadpool thread end up
                // invoking this event handler. The above lock and IsOpen check
                // ensures that we raise the event only when the port is open

                bool raiseEvent = false;
                try {
                    raiseEvent = stream.IsOpen && (SerialData.Eof == e.EventType || BytesToRead >= receivedBytesThreshold);
                }
                catch {
                    // Ignore and continue. SerialPort might have been closed already!
                }
                finally {
                    if (raiseEvent)
                        eventHandler(this, e);  // here, do your reading, etc.
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

请注意lock (stream)此代码中的语句。您还可以看到除非收到某些内容,否则不会调用您的 DataReceived 事件处理程序。并且您必须注意 SerialData.Eof 事件类型,这让相当多的程序员感到困惑。

你不必帮忙。