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

查看:88
本文介绍了创建确定性轮询线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,


我有一个小应用程序需要每隔10到15毫秒轮询一个设备(CAN

通信),否则硬件缓冲区可能

在总线上有消息突发时溢出。我会实现一个

中断驱动模型,但外部设备(通过USB连接

)不支持中断,因此设备需要

按特定时间间隔进行调查。所以我的问题是如何实现

确定性" C#(.NET)中的轮询机制?


目前,一旦CAN通信类被实例化,它就会创建一个轮询线程,使用

System.Threading.Thread类,线程创建机制

看起来像


//注意:所有错误检查都从样本中删除代码

ThreadStart threadDelegate = new

ThreadStart(PollingThreadDelegate);

m_PoolingThread = new Thread(threadDelegate);

m_PoolingThread.IsBackground = true;

m_PoolingThread.Priority = ThreadPriority.AboveNormal;

m_PoolingThread.Start();


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


private void PollingThreadDelegate()

{

while(true)

{

// 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然后引发一个事件,以便上层可以检索

来自队列的

//消息

}


我对当前实现的问题是

轮询线程需要是确定性的,并且在间隔时间内触发不会超过15毫秒,否则在通信突发期间很可能会丢弃

消息。我尽可能地调整了应用程序

,但是我拥有的仪器(FreqCnt)

告诉我最差情况时间已经在100毫秒时间范围内。

Hello all,

I have a little application that needs to poll a device (CAN
communications) every 10 to 15 ms otherwise the hardware buffer might
overflow when there are message burst on the bus. I would implement an
interrupt driven model, but the external device (which is connected
via USB) does not support interrupts therefore the device needs to be
polled at a specific interval. So my question is how can I implement a
"deterministic" polling mechanism in C# (.NET)?

Currently, once the CAN communications class is instantiated it
creates a polling thread which is implemented using the
System.Threading.Thread class which the thread creation mechanism
looks like

// Note: All error checking was removed from sample code
ThreadStart threadDelegate = new
ThreadStart(PollingThreadDelegate);
m_PoolingThread = new Thread(threadDelegate);
m_PoolingThread.IsBackground = true;
m_PoolingThread.Priority = ThreadPriority.AboveNormal;
m_PoolingThread.Start();

Then in the method which implements the thread delegate looks like

private void PollingThreadDelegate( )
{
while ( true )
{
// FreqCnt is of type 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 );

// Perform Read from USB interface to retrieve message from
the CAN
// device and place them in a queue

// Once all messages have been retrieved and if message count
greater
// than 0 then raise an event so the upper layer can retrieve
the
// message from the queue
}

The problem that I have with the current implementation is that
polling thread needs to be deterministic and trigger at an interval no
greater than 15 ms otherwise there is a high chance of dropping
messages during communications burst. I have tweaked the application
to the best of my ability, but instrumentation that I have (FreqCnt)
tells me the worst case timing has been in the 100 ms time frames.


>从其他工具中,应用程序通常会下降大约2到
>From other instrumentation generally the application drops about 2 to



3%的消息是一个很高的费率。


我不知道如何创建线程所以它是确定性的所以

应用程序不会丢弃任何消息。由于CAN通信

线程不在同一个线程上创建了表示层,

显示了用户的信息,需要一个代表(正确

term?)所以进程可以返回创建

控件的线程来更新控件(使用MethodInvoker实现)。


我尝试了几种不同的方法,但它们都没有正确地工作

。我已经尝试取出m_PoolingThread.Join语句,

但是然后轮询线程会使系统的其余部分变得饥饿,因为可以使用
图像,尤其是表示线程。另外,我已经尝试了不同的ThreadPriority级别,但是没有任何帮助。


非常感谢任何帮助。


Mark

3 percent of the messages which is a high rate.

I am not sure how to create the thread so it is deterministic so the
application doesn''t drop any messages. Since the CAN communications
thread is not on the same thread the created the presentation layer,
which displays the information for the user, needs a delegate (correct
term?) so the process can return to the thread that created the
controls to update the controls (implemented using the MethodInvoker).

I have tried several different approaches, but none of them work
correctly. I have tried taking out the m_PoolingThread.Join statement,
but then polling thread starves the rest of the system as one could
image and especially the presentation thread. In addition, I have
tried different ThreadPriority levels though none of them help.

Any help is greatly appreciated.

Mark

推荐答案

Mark,


有点好奇,为什么不呢从

System.Threading命名空间创建一个Timer实例。您可以将间隔设置为15ms,然后轮询

您的资源。你现在拥有的是一个有点做作的人,而且我没有看到任何真正的好处就是创建一个单独的线程只是为了等待

的时间间隔。 />
-

- Nicholas Paldino [.NET / C#MVP]

- mv*@spam.guard.caspershouse.com


< Lo ***** @ gmail.comwrote in message

news:11 ********************** @ y80g2000hsf.googlegr oups.com ...
Mark,

Kind of curious, why not just create a Timer instance from the
System.Threading namespace. You can set the interval for 15ms and then poll
your resource then. What you have now is a little contrived, and I don''t
see any real benefit to creating a separate thread just to wait for
intervals of time.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

<Lo*****@gmail.comwrote in message
news:11**********************@y80g2000hsf.googlegr oups.com...

大家好,

我有一个小应用程序需要每10到15毫秒轮询一个设备(CAN

通信),否则硬件缓冲区可能

在总线上有消息突发时溢出。我会实现一个

中断驱动模型,但外部设备(通过USB连接

)不支持中断,因此设备需要

按特定时间间隔进行调查。所以我的问题是如何实现

确定性" C#(.NET)中的轮询机制?


目前,一旦CAN通信类被实例化,它就会创建一个轮询线程,使用

System.Threading.Thread类,线程创建机制

看起来像


//注意:所有错误检查都从样本中删除代码

ThreadStart threadDelegate = new

ThreadStart(PollingThreadDelegate);

m_PoolingThread = new Thread(threadDelegate);

m_PoolingThread.IsBackground = true;

m_PoolingThread.Priority = ThreadPriority.AboveNormal;

m_PoolingThread.Start();


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


private void PollingThreadDelegate()

{

while(true)

{

// 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更高,那么就举起一个事件上层可以从队列中检索

//消息

}


我对当前实现的问题是

轮询线程需要是确定性的,并且在一个时间间隔内触发没有

大于15 ms否则很有可能掉线

通信突发期间的消息。我尽可能地调整了应用程序

,但是我拥有的仪器(FreqCnt)

告诉我最差情况时间已经在100毫秒时间范围内。
Hello all,

I have a little application that needs to poll a device (CAN
communications) every 10 to 15 ms otherwise the hardware buffer might
overflow when there are message burst on the bus. I would implement an
interrupt driven model, but the external device (which is connected
via USB) does not support interrupts therefore the device needs to be
polled at a specific interval. So my question is how can I implement a
"deterministic" polling mechanism in C# (.NET)?

Currently, once the CAN communications class is instantiated it
creates a polling thread which is implemented using the
System.Threading.Thread class which the thread creation mechanism
looks like

// Note: All error checking was removed from sample code
ThreadStart threadDelegate = new
ThreadStart(PollingThreadDelegate);
m_PoolingThread = new Thread(threadDelegate);
m_PoolingThread.IsBackground = true;
m_PoolingThread.Priority = ThreadPriority.AboveNormal;
m_PoolingThread.Start();

Then in the method which implements the thread delegate looks like

private void PollingThreadDelegate( )
{
while ( true )
{
// FreqCnt is of type 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 );

// Perform Read from USB interface to retrieve message from
the CAN
// device and place them in a queue

// Once all messages have been retrieved and if message count
greater
// than 0 then raise an event so the upper layer can retrieve
the
// message from the queue
}

The problem that I have with the current implementation is that
polling thread needs to be deterministic and trigger at an interval no
greater than 15 ms otherwise there is a high chance of dropping
messages during communications burst. I have tweaked the application
to the best of my ability, but instrumentation that I have (FreqCnt)
tells me the worst case timing has been in the 100 ms time frames.

>>从其他工具中,应用程序通常会下降大约2到
>>From other instrumentation generally the application drops about 2 to



3%的消息是一个很高的价格。


我不知道如何创建线程所以它是确定性的所以

应用程序不会丢弃任何消息。由于CAN通信

线程不在同一个线程上创建了表示层,

显示了用户的信息,需要一个代表(正确

term?)所以进程可以返回创建

控件的线程来更新控件(使用MethodInvoker实现)。


我尝试了几种不同的方法,但它们都没有正确地工作

。我已经尝试取出m_PoolingThread.Join语句,

但是然后轮询线程会使系统的其余部分变得饥饿,因为可以使用
图像,尤其是表示线程。另外,我已经尝试了不同的ThreadPriority级别,但是没有任何帮助。


非常感谢任何帮助。


Mark

3 percent of the messages which is a high rate.

I am not sure how to create the thread so it is deterministic so the
application doesn''t drop any messages. Since the CAN communications
thread is not on the same thread the created the presentation layer,
which displays the information for the user, needs a delegate (correct
term?) so the process can return to the thread that created the
controls to update the controls (implemented using the MethodInvoker).

I have tried several different approaches, but none of them work
correctly. I have tried taking out the m_PoolingThread.Join statement,
but then polling thread starves the rest of the system as one could
image and especially the presentation thread. In addition, I have
tried different ThreadPriority levels though none of them help.

Any help is greatly appreciated.

Mark



2007年4月11日星期三09:35:25 -0700,< Lo ***** @ gmail.com写道:
On Wed, 11 Apr 2007 09:35:25 -0700, <Lo*****@gmail.comwrote:

[...]

我对当前实现的问题是

轮询线程需要是确定性的,并且在间隔时间内触发不会超过15毫秒,否则在通信突发期间很有可能丢弃

消息。
[...]
The problem that I have with the current implementation is that
polling thread needs to be deterministic and trigger at an interval no
greater than 15 ms otherwise there is a high chance of dropping
messages during communications burst.



Windows不是实时操作系统,因此无法保证

线程在特定的时间间隔内运行时间。无论如何,

总是有可能你的线程在运行间隔时间比所需的15ms长得多。


也就是说,在现代PC的背景下,15ms是相当长的时间。

你可能在缩短你的轮询间隔方面取得了一些成功,因为

例如,5毫秒。仍然没有保证,但它可能会更好。


我很少被使用Join处理线程阻塞感到困惑,

自你(如果我正确地阅读了代码)正在加入当前线程。

虽然超时确实可以防止实际发生死锁,但对我来说似乎是坏的形式。我只想使用Sleep(如果应该有

无法提前唤醒线程)或等待超时事件(如果需要唤醒
)在某些情况下早期的线程)。


我也对这不可能是中断驱动的声明感到困惑,因为

我的印象是Windows下的USB控制器都使用

中断驱动的i / o。但是我猜测我在Windows下误解了USB

,或者我真的不明白你使用的硬件连接是什么?b $ b使用。我会认为只是以中断驱动的方式从USB

端口读取数据是不可能的。


"右"修复此问题的方法可能是为您的

设备编写驱动程序。这不是真正的C#/。NET问题。


Pete

Windows is not a real-time OS, so there is no way to guarantee that a
thread will run within a specific interval of time. No matter what, there
will always be the possibility that your thread goes a lot longer between
run intervals than the required 15ms.

That said, in the context of the modern PC, 15ms is a pretty long time.
You might have some success in shortening your polling interval to, for
exampl5, 5ms. There are still no guarantees but it might work better.

I''m a little puzzled by the use of Join to deal with the thread blocking,
since you (if I read the code right) are joining to the current thread.
While the timeout does prevent deadlock from actually happening, it seems
like bad form to me. I would instead just use Sleep (if there should be
no way to wake the thread up early) or wait on an event with a timeout (if
you need to wake the thread up early in some situations).

I''m also puzzled by the statement that this can''t be interrupt-driven, as
I was under the impression that USB controllers under Windows all use
interrupt-driven i/o. But I''m guessing that either I''m mistaken about USB
under Windows, or I don''t really understand the hardware connection you''re
using. I''ll take as granted that simply reading in the data from the USB
port in an interrupt-driven way isn''t possible.

The "right" way to fix this would probably be to write a driver for your
device. That''s not really a C#/.NET question though.

Pete


2007年4月11日星期三09: 56:06 -0700,Nicholas Paldino [.NET / C#MVP]

< mv*@spam.guard.caspershouse.comwrote:
On Wed, 11 Apr 2007 09:56:06 -0700, Nicholas Paldino [.NET/C# MVP]
<mv*@spam.guard.caspershouse.comwrote:

Mark,


有点好奇,为什么不从

System.Threading命名空间创建一个Timer实例。您可以将间隔设置为15毫秒,然后

轮询您的资源。你现在拥有的是一个有点做作的人,而且我没有b $ b看到创建一个单独的线程只是为了等待
$ b的任何真正的好处。 $ b的时间间隔。
Mark,

Kind of curious, why not just create a Timer instance from the
System.Threading namespace. You can set the interval for 15ms and then
poll your resource then. What you have now is a little contrived, and I
don''t
see any real benefit to creating a separate thread just to wait for
intervals of time.



对于它的价值,我会说不使用Timer类的一个原因是

如果对于某些人来说因为代理在期望的

定时器间隔期间没有执行,最终会有多个排队的定时器。如果代表执行时间过长(希望不太可能),这可能会发生



或者如果出于某种原因,定时器的一次触发不会在下一个之前执行

(这更有可能,并且可能由于线程

调度问题或竞争线程池线程而发生)。


使用专用线程,线程本身可以弄清楚执行计时器的成本是多少以及确保它不浪费时间

在它刚刚清空输入缓冲区时第二次执行。当然,

所发布的代码并没有做到这一点,但它可能(并且可能是

应该)。 :)


Pete

For what it''s worth, I''d say one reason to not use the Timer class is that
if for some reason the delegate doesn''t get executed during the desired
timer interval, one winds up with multiple queued timers. This can happen
if the delegate takes too long to execute (hopefully that''s less likely)
or if for some reason one firing of the timer doesn''t get to execute
before the next one (this is more likely, and can happen due to thread
scheduling issues or competition for thread pool threads).

Using a dedicated thread, the thread can itself figure out what the cost
of executing the timer is as well as ensuring that it doesn''t waste time
executing a second time when it''s just emptied the input buffer. Granted,
the code posted doesn''t do any of this, but it could (and probably
should). :)

Pete


这篇关于创建确定性轮询线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆