3

我正在开发一个使用 8 个 COM 端口的应用程序,当从一个 COM 端口接收数据时,调用事件处理程序,应用程序为通过 COM 端口接收的消息创建包装器,并通过 TCP 将其发送到远程主机。事实上,在包装之后,它成为基于以太网的网络中某处设备的命令(开始测量命令)。

我正在使用 SerialPort 和 SerialDataReceivedEventHandler 来处理 COM 端口。问题是我通过表单为每个 COM 端口指定了不同的超时(0-1000 毫秒)。在此超时之后,我必须发送另一个命令以从设备获取一些数据(获取数据命令)。

  • 此命令对于 8 个 COM 端口中的每一个都不同
  • 只有在通过 COM 端口接收数据并发送第一个命令后才能发送此命令
  • 两个命令之间的超时对于每个 com 端口都不同

您对超时组织有什么建议吗?谢谢。

我有一个想法,但我不确定是否可能:每个 COM 端口都有 8 个事件处理函数。

...something
sendFirstCommand();
Thread.Sleep(comPortNTimeout);
sendSecondCommand();

我可以在每个人中使用相同的结构吗?例如,如果数据 Thread.Sleep() 将在第二个端口的处理程序中被调用,第一个端口的处理程序是否会被冻结?

4

1 回答 1

2

1)引入某种CommandSourceContext类来封装与每个COM端口相关的所有参数(见下文)

2) 要查看处理程序是否会在引发其他端口事件时冻结 - 只需在调试器中测试它并查看是否在同一线程中调用了所有端口事件。您可以使用 Visual Studio 2010 线程窗口,只需在 COM 端口事件处理程序中放置一个断点,然后查看当前线程 ID 是什么。如果您使用的是旧版 Visual Studio - 只需记录通过Thread.CurrentThread.ManagedThreadId. 因此,如果在同一个线程中调用来自不同端口的事件 - 显然处理程序会阻塞每个端口,否则会因为在不同线程中调用而并行运行。至少 MSDN 说(请参阅此答案的底部)接收到的数据事件不是在主线程中引发的,因此在访问 UI 控件时必须小心。

interface ICommandSourceContext
{
   // Since each port has own specific command
   // we can encapsulate it in the context as well
   ICommand Command { get; }

   int PortNumber { get; }
   long TimeIntervalMilliseconds { get; }
   Action<SerialDataReceivedEventArgs> Callback { get; }     
}

// setup and add all contexts
IList<ICommandSourceContext> contexts = new List<ICommandSourceContext>();

// ideally your main code block should looks like below (this is only pseudo code)
foreach (var context in contexts)
{
   // to execute it asyncronously you can use TPL Task.Start()
   // so it would not block other handlers in case of single thread
   context.Command.Execute();
   Thread.Sleep(context.TimeIntervalMilliseconds);
}

SerialPort.DataReceived 事件备注

从 SerialPort 对象接收数据时,在辅助线程上引发DataReceived事件。由于此事件是在辅助线程而不是主线程上引发的,因此尝试修改主线程中的某些元素(例如 UI 元素)可能会引发线程异常。如果需要修改主窗体或控件中的元素,请使用 Invoke 将更改请求发回,这将在适当的线程上完成工作

于 2012-06-25T12:18:31.910 回答