创建确定性轮询线程[英] Creating a deterministic polling thread

问题描述

大家好,

我有一个需要轮询设备的小应用程序(CAN
通信)每 10 到 15 毫秒,否则硬件缓冲区可能
当总线上有消息突发时溢出.我会实施一个
中断驱动模型,但外部设备(这是连接的
通过 USB)不支持中断,因此设备需要
以特定间隔轮询.所以我的问题是如何实现一个
"确定性"C#(.NET)中的轮询机制?

目前,一旦 CAN 通信类被实例化,它
创建一个使用
实现的轮询线程System.Threading.Thread 类里面的线程创建机制
好像

//注意:示例代码中删除了所有错误检查
ThreadStart threadDelegate = new
ThreadStart(PollingThreadDelegate);
m_PoolingThread = 新线程(threadDelegate);
m_PoolingThread.IsBackground = true;
m_PoolingThread.Priority = ThreadPriority.AboveNormal;
m_PoolingThread.Start();

然后在实现线程委托的方法中看起来像

私有 void PollingThreadDelegate( )
{
而(真)
{
//FreqCnt 的类型是 System.Diagnostics.Stopwatch
FreqCnt.Stop();
if ( FreqCnt.ElapsedMilliseconds WorstTime )
{
WorstTime = FreqCnt.ElapsedMilliseconds;
}
FreqCnt.Reset();
FreqCnt.Start();

m_RxThreadIsActive = false;
m_PoolingThread.Join( (int)m_ScanModeInterval );

//执行从 USB 接口读取以从
中检索消息CAN
//设备并将它们放入队列中

//一旦所有消息都被检索并且如果消息计数
更大的
//大于 0 则引发事件,以便上层可以检索

//来自队列的消息
}

我对当前实现的问题是
轮询线程需要是确定性的,并且在间隔内触发 no
大于 15 毫秒,否则很有可能掉线
通信突发期间的消息.我已经调整了应用程序
尽我所能,但我拥有的仪器 (FreqCnt)
告诉我最坏的情况是在 100 毫秒的时间范围内.

>从其他仪器来说,应用程序通常下降大约 2 到
3% 的消息率很高.

我不确定如何创建线程,所以它是确定性的,所以
应用程序不会丢弃任何消息.自CAN通讯
线程不在创建表示层的同一线程上,
为用户显示信息,需要委托(正确
术语?)所以进程可以返回到创建
的线程控件来更新控件(使用 MethodInvoker 实现).

我尝试了几种不同的方法,但没有一个有效
正确.我已经尝试取出 m_PoolingThread.Join 语句,
但是轮询线程会尽可能地使系统的其余部分饿死
图像,尤其是演示线程.另外,我有
尝试了不同的 ThreadPriority 级别,但都没有帮助.

非常感谢任何帮助.

Mark

推荐答案

Mark,

有点好奇,为什么不直接从
创建一个 Timer 实例System.Threading 命名空间.可以设置间隔为15ms,然后轮询
那么你的资源.你现在做的有点做作,我没有
看看创建一个单独的线程只是为了等待有什么真正的好处
时间间隔.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

<Lo*****@gmail.com 在留言中写道
新闻:11**********************@y80g2000hsf.googlegr oups.com...
大家好,

我有一个需要轮询设备的小应用程序(CAN
通信)每 10 到 15 毫秒,否则硬件缓冲区可能
当总线上有消息突发时溢出.我会实施一个
中断驱动模型,但外部设备(这是连接的
通过 USB)不支持中断,因此设备需要
以特定间隔轮询.所以我的问题是如何实现一个
"确定性"C#(.NET)中的轮询机制?

目前,一旦 CAN 通信类被实例化,它
创建一个使用
实现的轮询线程System.Threading.Thread 类里面的线程创建机制
好像

//注意:示例代码中删除了所有错误检查
ThreadStart threadDelegate = new
ThreadStart(PollingThreadDelegate);
m_PoolingThread = 新线程(threadDelegate);
m_PoolingThread.IsBackground = true;
m_PoolingThread.Priority = ThreadPriority.AboveNormal;
m_PoolingThread.Start();

然后在实现线程委托的方法中看起来像

私有 void PollingThreadDelegate( )
{
而(真)
{
//FreqCnt 的类型是 System.Diagnostics.Stopwatch
FreqCnt.Stop();
if ( FreqCnt.ElapsedMilliseconds WorstTime )
{
WorstTime = FreqCnt.ElapsedMilliseconds;
}
FreqCnt.Reset();
FreqCnt.Start();

m_RxThreadIsActive = false;
m_PoolingThread.Join( (int)m_ScanModeInterval );

//执行从 USB 接口读取以从
中检索消息CAN
//设备并将它们放入队列

//一旦所有消息都被检索并且如果消息计数
更大的
//大于 0 则引发事件,以便上层可以检索

//来自队列的消息
}

我对当前实现的问题是
轮询线程需要是确定性的,并且在间隔内触发 no
大于 15 毫秒,否则很有可能掉线
通信突发期间的消息.我已经调整了应用程序
尽我所能,但我拥有的仪器 (FreqCnt)
告诉我最坏的情况是在 100 毫秒的时间范围内.
>>从其他仪器来说,应用程序通常下降大约 2 到
3% 的消息率很高.

我不确定如何创建线程,所以它是确定性的,所以
应用程序不会丢弃任何消息.自CAN通讯
线程不在创建表示层的同一线程上,
为用户显示信息,需要委托(正确
术语?)所以进程可以返回到创建
的线程控件来更新控件(使用 MethodInvoker 实现).

我尝试了几种不同的方法,但没有一个有效
正确.我已经尝试取出 m_PoolingThread.Join 语句,
但是轮询线程会尽可能地使系统的其余部分饿死
图像,尤其是演示线程.另外,我有
尝试了不同的 ThreadPriority 级别,但都没有帮助.

非常感谢任何帮助.

Mark


2007 年 4 月 11 日星期三 09:35:25 -0700,<Lo*****@gmail.com 写道:
[...]
我对当前实现的问题是
轮询线程需要是确定性的,并且在间隔内触发 no
大于 15 毫秒,否则很有可能掉线
通信突发期间的消息.
Windows 不是实时操作系统,所以没有办法保证一个
线程将在特定的时间间隔内运行.不管怎样,有
总是有可能你的线程在
运行间隔比要求的15ms.

也就是说,在现代 PC 的背景下,15 毫秒是相当长的时间.
您可能会在将轮询间隔缩短到以下方面取得一些成功,因为
示例 5,5 毫秒.仍然没有保证,但它可能会更好.

使用Join处理线程阻塞,我有点疑惑,
因为你(如果我没看错的话)正在加入当前线程.
虽然超时确实可以防止死锁实际发生,但似乎
对我来说就像糟糕的形式.我宁愿只使用睡眠(如果应该有
无法提前唤醒线程)或等待超时事件(如果
在某些情况下,您需要提前唤醒线程).

我也对不能中断驱动的说法感到困惑,因为
我的印象是Windows下的USB控制器都用
中断驱动的 I/O.但我猜要么我对 USB 有误解
windows下,不然我不是很懂你是什么硬件连接
使用.我认为只是从 USB 读取数据是理所当然的
以中断驱动的方式进行端口是不可能的.

"权利"解决此问题的方法可能是为您的
编写驱动程序设备.不过,这并不是一个真正的 C#/.NET 问题.

皮特

2007 年 4 月 11 日星期三 09:56:06 -0700,Nicholas Paldino [.NET/C# MVP]
<mv*@spam.guard.caspershouse.com 写道:
马克,

有点好奇,为什么不直接从
创建一个 Timer 实例System.Threading 命名空间.您可以将间隔设置为15ms,然后
然后轮询您的资源.你现在的东西有点做作,而我
不要
看看创建一个单独的线程只是为了等待有什么真正的好处
时间间隔.
对于它的价值,我想说不使用 Timer 类的一个原因是
如果由于某种原因委托在期望的期间没有被执行
计时器间隔,一个以多个排队计时器结束.这可能会发生
如果委托执行时间过长(希望不太可能)
或者如果由于某种原因一次触发计时器没有执行
在下一个之前(这更有可能,并且可能由于线程而发生
调度问题或线程池线程竞争).

使用专用线程,线程可以自己算出代价是什么
执行计时器以及确保它不会浪费时间
当它刚刚清空输入缓冲区时再次执行.诚然,
发布的代码没有做任何这些,但它可以(并且可能
应该).:)

皮特

本文地址:https://www.itbaoku.cn/post/1050465.html