Creating a deterministic polling thread

L

LordHog

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.
From other instrumentation generally the application drops about 2 to
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
 
N

Nicholas Paldino [.NET/C# MVP]

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.
 
P

Peter Duniho

[...]
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 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
 
P

Peter Duniho

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.

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
 
L

LordHog

[...]
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 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

Pete,

Thanks for the comments, just a quick few comments. I have attempted
to drop the interval from 15 to 10 to 5 and even 1 ms, though it never
helped out in the long run. While it may be true that USB does indeed
support interrupts the particular piece of hardware does not support
interrupt on the controller side. From the external device (which is
purchased from an outside vendor) it goes from a MCP2515 CAN
Controller to a uController then to the USB interface. Though the USB
interface supports hardware interrupts the uController will never
raise an interrupt from my current understanding.

I have tried both the Sleep() and Join() methods, but both methods
produce the same results. I do agree with using Join in this scenario
is bad form as I am not truly waiting for another thread to signal and
I was only using the timeout feature of the Join() method.

Another I would ask, would creating a polling mechanism in Visual C+
+ produce better results?

Mark
 
P

Peter Duniho

[...]
// 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

One additional comment...

In replying to Nicholas's post, I realized that you always wait in your
thread for a constant amount of time. IMHO, it would be better to
subtract the time it took to process the receive from your nominal wait
interval. That is, the time inside your loop that occurs once you believe
you've emptied the input buffer but before you start waiting again. That
will ensure that the total wait time is not unduly affected by code
executing but not receiving data.

The other thing I noticed is that in your comment about receiving data,
you write "raise an event so the upper layer can retrieve the message from
the queue". It's not clear what you mean by "raise an event", since the
code isn't actually shown, but if you're using a C# event data type and
calling it to process the data, this could be the reason for the large
delays in your receiving code.

Specifically, when you "raise an event" in .NET using the event/delegate
paradigm, the event is handled on the thread that raised the event in the
first place (usually by calling an "OnXXX" method that runs the event
handlers).

Your receiving thread should *only* be receiving and copying the data
somewhere. Once the data is in a queue, then some means of signaling to
another thread to do the actual processing can be used. This might be by
using BeginInvoke on your UI form or some control on the form, if the
"actual processing" is primarily for user output, or you might have
another thread dedicated to actually processing the data, if you're doing
something more complex with it (like writing it to a file or something).

The problem here is the ambiguity in the use of the word "event" when it
comes to .NET programming. It could have either the traditional Windows
API meaning related to an "event handle", or it could have the new .NET
meaning related to events and their event handlers (special delegates
called when you process the event). Since you didn't post the actual code
for that, we don't know which one of those meanings you're using when you
write "event".

Pete
 
L

LordHog

Nicholas,

Thanks for the feedback, unfortunately my first implementation used
a Timer and it didn't produced any better results than the current
implementation. The main reason I created a separate thread was no to
starve the GUI so it didn't seems unresponsive. Perhaps a Timer
mechanism might be better in the long run, but I couldn't get it to
work correctly.

Mark



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]
- (e-mail address removed)


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.
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.
 
C

Chris Mullins [MVP]

I would tend to shy away from a Timer based approach - 15 milliseconds isn't
very long, and it's very easy to end up missing a timer interval. I'm not
even sure if any timers (other than the MultiMedia Win32 Timers) are
accurate at resolutions smaller than 60 milliseconds.

I would lean towards a dedicated thread that is continually in a
While(!shutdown) loop, continually polling data. and using a SpinWait to
wait between polls. You may also be forced to play some thread Priority
games (which are very dangerous, and tough to get right), in order to make
sure you don't miss any polling cycles.

When you pull data out of the USB buffer, you'll want to put it into your
own buffer. You'll also want to tickel an Event of some sort (probably a
ManualResetEvent) saying you've got data. This will allow other threads to
wake up and do something usefull with the data.

Joe Duffy has talked a little bit about how all this works at:
http://www.bluebytesoftware.com/blog/PermaLink,guid,1c013d42-c983-4102-9233-ca54b8f3d1a1.aspx
 
P

Peter Duniho

[...]
Another I would ask, would creating a polling mechanism in Visual C+
+ produce better results?

Doubtful. The timing limitations here are inherent to Windows. There's a
little overhead to running .NET code, but not much.

Please see my other follow-up reply, for other possible improvements to
your design. The more I think about it, the more I don't see why you
should sometimes see delays of as much as 100ms, unless you're causing
those delays yourself in the code that handles the data after it's been
received. 100ms is a LOT of time for a modern computer. A HUGE amount of
time. :)

By the way, based on your comment that you tried changing the thread
priority, I am making the assumption that your data receiving thread is
not being hindered by other threads running on the computer (in your
process or in other processes) that use up their full time quanta.
Assuming such other threads would be running at a lower priority than the
priority you tried then at most only one should be able to monopolize the
CPU between your own thread's execution, and the thread quantum is much
much smaller than the tens or hundreds of millisecond delays you're seeing.

That is, it doesn't sound like your process is being interfered with by
other processes, and is instead intefering with itself all by itself. But
if my assumptions are wrong, that would be something to consider as well.
Again, since Windows isn't a real-time OS, you can always run into a
situation where other processes get in the way of your own process getting
CPU time exactly when you want it.

Pete
 
N

Nicholas Paldino [.NET/C# MVP]

Mark,

Were you using a Timer from the System.Windows.Forms namespace (which I
think is the case because you said you were starving the UI) or from the
System.Threading namespace? If you used the latter, then the timer event
should be fired on a non UI thread.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Nicholas,

Thanks for the feedback, unfortunately my first implementation used
a Timer and it didn't produced any better results than the current
implementation. The main reason I created a separate thread was no to
starve the GUI so it didn't seems unresponsive. Perhaps a Timer
mechanism might be better in the long run, but I couldn't get it to
work correctly.

Mark



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]
- (e-mail address removed)


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.
From other instrumentation generally the application drops about 2 to
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.
 
P

Peter Duniho

[...]
I would lean towards a dedicated thread that is continually in a
While(!shutdown) loop, continually polling data. and using a SpinWait to
wait between polls. You may also be forced to play some thread Priority
games (which are very dangerous, and tough to get right), in order to
make sure you don't miss any polling cycles.

Keeping in mind, of course, that SpinWait does nothing except tie up the
CPU rather than yielding control. IMHO, in this situation it has pretty
much the same effect as just polling without any sort of yielding
mechanism at all, since either way the thread will use up its entire
quantum and nothing else can happen in the duration.

And of course, Chris is right to caution that messing with thread priority
can be dangerous. It's hazardous enough when you have a thread that
yields, but one that consumes its entire quantum every time can completely
trash system performance, especially if it's the only (or one of the few)
threads at that priority or higher (and very few threads run above normal
priority).

Chris is correct that the thread scheduler-based timing methods aren't
very high resolution. But going the other way can be very dangerous
indeed, with respect to the responsiveness of the system as a whole.

Pete
 
L

LordHog

All,

Okay, to help understand my application a little better there are
actually several layers of the communications. (Please forgive my
naming conventions)

CAN Communications Class:
At the lowest level in my application is the CAN Communications
Class which interfaces with the USB APIs to talk with the external
devices. This is the class which implements the polling thread.
Messages collected are placed into a collection which are CAN
specific. Data from the upper layers are packaged to conform to the
manufactures APIs to provide a level of abstraction. This class
implements a delegate interface (is that the correct term?) which the
CAN Communicaitons Class derives an event from. These are declared as
follows:

// CommMsgEventTypes is basically an enumeration that list message
types
public delegate void CommMsgEventHandler( object source,
CommMsgEventTypes e );

public event CommMsgEventHandler OnCommMsgEvent;

Once messages have arrived the CommMsgEventHandler event is raised
(correct term?) to inform the upper layer there are messages in the
queue.



LRU Communications Class:
This class implements the communications protocol that are specific
to the LRU and will provide another level of abstraction for the
presentation layer (GUI interface). This class instantiates an object
of type "CAN Communications Class" then registers a method that will
handle the OnCommMsgEvent event. When the OnCommMsgEvent event
triggers the method that is mapped to the OnCommMsgEvent. There is one
item which will happen 1) Another event will be raised
(OnSDUCanMsgEvent) which informs the upper layer CAN messages have
arrived. The delegate and event declaration looks like the following:

public delegate void SDUCanMsg( );

public event SDUCanMsg OnSDUCanMsgEvent;


Presentation Layer (GUI)
This class implements the GUI which the operator interacts with, CAN
Communications and logging of data. This class instantiates an object
of type "LRU Communications Class". The class registers with the
"OnSDUCanMsgEvent" provided by the "LRU Communications Class". The
method that is mapped to this event is written as


private void CanCommInterface_SDUCanMsgEvent( )
{
if (this.IsHandleCreated)
{
// Note: m_SDUCanMsgDelegate is of tpye
MethodInvoker
this.BeginInvoke( this.m_SDUCanMsgDelegate );
}
}

The m_SDUCanMsgDelegate is mapped to a method which will call an
interface method provided by the "LRU Communications Class" to read
each LRU CAN message in turn until all messages have been processed.
The "LRU Communications Class" provides an interface to retrieve each
CAN message which will be decode for the presentation layer. I was
going to decode the message when the "OnCommMsgEvent" event is
triggered in the "LRU Communications Class", but I didn't want to
create any additional overhead. So I decided to decode them when the
presentation layer dequeued each message.


I assume during the BeginInvoke call the execution will return to
the polling thread then at some time later the GUI thread will kick in
and pull each message from the "LRU Communications Class".

I hope that helps a little and doesn't confuse the issue too much.
Hard to write it down clearily and concisely.

Mark

P.S. Sorry, I am not sure I should be top or bottom posting, so please
forgive me.



[...]
// 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

One additional comment...

In replying to Nicholas's post, I realized that you always wait in your
thread for a constant amount of time. IMHO, it would be better to
subtract the time it took to process the receive from your nominal wait
interval. That is, the time inside your loop that occurs once you believe
you've emptied the input buffer but before you start waiting again. That
will ensure that the total wait time is not unduly affected by code
executing but not receiving data.

The other thing I noticed is that in your comment about receiving data,
you write "raise an event so the upper layer can retrieve the message from
the queue". It's not clear what you mean by "raise an event", since the
code isn't actually shown, but if you're using a C# event data type and
calling it to process the data, this could be the reason for the large
delays in your receiving code.

Specifically, when you "raise an event" in .NET using the event/delegate
paradigm, the event is handled on the thread that raised the event in the
first place (usually by calling an "OnXXX" method that runs the event
handlers).

Your receiving thread should *only* be receiving and copying the data
somewhere. Once the data is in a queue, then some means of signaling to
another thread to do the actual processing can be used. This might be by
using BeginInvoke on your UI form or some control on the form, if the
"actual processing" is primarily for user output, or you might have
another thread dedicated to actually processing the data, if you're doing
something more complex with it (like writing it to a file or something).

The problem here is the ambiguity in the use of the word "event" when it
comes to .NET programming. It could have either the traditional Windows
API meaning related to an "event handle", or it could have the new .NET
meaning related to events and their event handlers (special delegates
called when you process the event). Since you didn't post the actual code
for that, we don't know which one of those meanings you're using when you
write "event".

Pete
 
L

LordHog

Nicholas,

I don't recall off the top of my head, but more than likely it was
the Timer from the System.Windows.Form namespace as you have
indicated.

Mark



Mark,

Were you using a Timer from the System.Windows.Forms namespace (which I
think is the case because you said you were starving the UI) or from the
System.Threading namespace? If you used the latter, then the timer event
should be fired on a non UI thread.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Nicholas,
Thanks for the feedback, unfortunately my first implementation used
a Timer and it didn't produced any better results than the current
implementation. The main reason I created a separate thread was no to
starve the GUI so it didn't seems unresponsive. Perhaps a Timer
mechanism might be better in the long run, but I couldn't get it to
work correctly.
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]
- (e-mail address removed)

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.
From other instrumentation generally the application drops about 2 to
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
 
P

Peter Duniho

[...]
I assume during the BeginInvoke call the execution will return to
the polling thread then at some time later the GUI thread will kick in
and pull each message from the "LRU Communications Class".

If I read all that right, then yes basically all that happens in your i/o
thread (the one that receives data from the USB controller) is that you
store the data somewhere and post a message to the GUI (BeginInvoke()).

That *ought* to be fine, though you do have more layering than might
strictly-speaking be desirable, and of course we don't know how you're
maintaining the queue of received data (hopefully it's something that is
very fast in adding elements to the queue).

Assuming you don't have any glaring performance issues in the code
executing within your i/o thread, there may not be any good solutions
here. When you let a thread yield control of the CPU, you're at the mercy
of the Windows thread scheduler to get control back and that's not a
reliable real-time mechanism.

Diagnostically, you might find it informative to time your code in shorter
sections. For sure, it would be useful to know how much time you spend
processing i/o and how much time you spend waiting when you call Sleep().
That should help you understand better whether you're dealing with some
performance issue in the i/o code, or if it's a thread scheduling issue.

I do agree that it would be worthwhile trying the Threading.Timer class,
but as has been mentioned that still relies on the thread scheduler and so
while it should give you better accuracy than the Forms.Timer class, there
are still no guarantees.
P.S. Sorry, I am not sure I should be top or bottom posting, so please
forgive me.

That's a whole other can of worms you're opening right there. Personally,
I think the biggest problem with top-posting is that people who top-post
fail to trim their quotes (as you did). But in the end, those who say
that top-posters will never change and it's not worth trying to convince
them otherwise, they are correct as well and so the discussion is probably
pointless.

Quote and post as you see fit...there's little anyone else can do about
it. :)

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top