【问题标题】:Interrogation organization, timeouts审讯组织、超时
【发布时间】:2012-06-25 11:57:29
【问题描述】:

我正在开发一个使用 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() 将在第二个端口的处理程序中调用,那么第一个端口的处理程序是否会被冻结?

【问题讨论】:

    标签: c# multithreading events serial-port


    【解决方案1】:

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

    2) 要查看在引发其他端口事件时处理程序是否会冻结 - 只需在调试器中测试它并查看是否所有端口事件都在同一线程中调用。您可以使用 Visual Studio 2010 线程窗口,只需在 COM 端口事件处理程序中放置一个断点,然后查看当前线程 ID 是什么。如果您使用的是旧版 Visual Studio - 只需记录通过 Thread.CurrentThread.ManagedThreadId 访问它的线程 ID。因此,如果在同一个线程中调用来自不同端口的事件 - 显然处理程序会阻塞每个端口,否则会因为在不同线程中调用而并行运行。至少 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 Event remarks:

    DataReceived 事件在数据接收时在辅助线程上引发 从 SerialPort 对象接收。因为这个事件是在一个 辅助线程,而不是主线程,试图修改一些 主线程中的元素,例如 UI 元素,可能会引发 线程异常。如果需要修改 main 中的元素 表单或控件,使用 Invoke 将更改请求发布回来,这样就可以了 在正确的线程上工作

    【讨论】:

    • 谢谢你,这篇文章真的很棒而且很有用。不幸的是,没有机会为我的工作站获得至少一个额外的串行端口。我以后只能测试这个问题。
    • 您可以创建很好的测试工具来模拟多个端口并确保您的实现工作正常,从长远来看这也适合您
    • 在实践中,如果我有 8 个 COM 端口设备用于这样的应用程序,我会使用其中一个 rs232 连接以太网设备,这样您的软件就可以直接处理以太网,而完全不会弄乱串行端口. perle.com/products/…
    猜你喜欢
    • 2018-11-07
    • 1970-01-01
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多