C# 审讯组织、暂停

C# 审讯组织、暂停,c#,multithreading,events,serial-port,C#,Multithreading,Events,Serial Port,我正在开发一个使用8个COM端口的应用程序,当从其中一个COM端口接收数据时,调用事件处理程序,应用程序为通过COM端口接收的消息创建包装器,并通过TCP将其发送到远程主机。事实上,包装后,它变成了基于以太网的网络中某个设备的命令(开始测量命令) 我使用SerialPort和SerialDataReceivedEventHandler处理COM端口。问题是我通过表单为每个COM端口指定了不同的超时(0-1000毫秒)。在此超时之后,我必须发送另一个命令以从设备获取一些数据(GETDATA命令)

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

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

  • 此命令对于8个COM端口中的每个端口都不同
  • 只有在通过COM端口接收数据并发送第一个命令后,才应发送此命令
  • 对于每个com端口,两个命令之间的超时是不同的
你对组织有什么建议吗?谢谢

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

...something
sendFirstCommand();
Thread.Sleep(comPortNTimeout);
sendSecondCommand();
我可以在每一个中使用相同的结构吗?如果在第二个端口的处理程序中调用data Thread.Sleep(),第一个端口的处理程序不会被冻结吗?

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);
}
接口ICommandSourceContext
{
//因为每个端口都有自己的特定命令
//我们也可以在上下文中封装它
ICommand命令{get;}
int端口号{get;}
长时间间隔毫秒{get;}
操作回调{get;}
}
//设置并添加所有上下文
IList contexts=新列表();
//理想情况下,主代码块应该如下所示(这只是伪代码)
foreach(上下文中的var上下文)
{
//要异步执行它,可以使用TPL Task.Start()
//因此,在单线程的情况下,它不会阻止其他处理程序
context.Command.Execute();
Sleep(context.timeintervalms);
}
:

读取数据时,在辅助线程上引发DataReceived事件 从SerialPort对象接收。因为此事件是在 次线程,而不是主线程,正在尝试修改某些 主线程中的元素(如UI元素)可能引发 线程异常。如果需要修改主视图中的图元 窗体或控件,使用Invoke将更改请求发回 在正确的螺纹上工作


谢谢你,这是一个非常棒和有用的帖子。不幸的是,没有机会为我的工作站获得至少一个额外的串行端口。我只能在将来测试这个问题。你可以创建一个很好的测试线束来模拟多个端口,并确保你的实现工作正常,从长远来看,这对你来说也是可行的,如果我有8个COM端口设备用于这样的应用程序,我会使用其中一个rs232到以太网设备,这样您的软件就可以直接处理以太网,而不会弄乱串行端口。