LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

InstallComCallback() blocked by timer.

I have 16 usb serial ports that Tx and Rx serial data.

I use  InstallComCallback() to set up each serial  port.

On one of the serial ports (57600 baud) I receive data and parse it.

As my application code has grown I noticed this parsing section slowing down and usig most of thePC  CPU.

I traced this to the RegExpr_FindPatternInText() call gradually taking longer and longer to execute.

 

The serial interrupt places the receved data into a buffer  for processing later.

I have a 0.100 second timer that processes all the serial buffers and places the received strings into a list box for viewing.

 

What I discovered is that while the timer is executing it blocks the serial interrupt routine which then lags behind and the data piles up causing more delays.

 

Is there anyway to have the serial interrupts execute on Rx data demand overriding the timer with higher priority?

0 Kudos
Message 1 of 6
(4,101 Views)
Probably the easiest thing to try would be to add some ProcessSystemEvents() calls into the timer callback.  Then, anytime  ProcessSystemEvents is called, anything that has been qued up should then go, like a ComCallback (as well as things like other timers, or events triggered by the user on the user interface). If that doesn't work, the only other thing I can think of trying would be to put the timer in another thread.  
0 Kudos
Message 2 of 6
(4,072 Views)

Hi tstanley.

 

I did a test earlier where I deleted the timer and essentially had no code running to test the interrupts and the serial buffers filled up with the expected data.

I then assumed, which was wrong on my part, that the serial comm interrupts preemptd the timer code.

I will call ProcessSystemEvents() in the timer routine.

Is there any rule of thumb when and where to call ProcessSystemEvents() and what hit it will have on other code?

 

Thanks.

0 Kudos
Message 3 of 6
(4,057 Views)

Put it right at the end, just before you return from the timer callback.

 

JR

0 Kudos
Message 4 of 6
(4,052 Views)

The biggest risk with the ProcessSystemEvents() calls is that something, like one of the Com callbacks could do something like modify global variables, and you could end up with a race condition, or other undesirable behavior if the timer callback is assuming that these globals do not change for the duration of the callback function.  The other risk is that the calls can "unlock" the user interface (which otherwise would be unresponsive while the timer callback is executing) and the user could push buttons, change settings, etc. while the callback function is running at any point where a ProcessSystemEvents() is called.

As JR suggested I would make sure there is a call at the very end, as this would have no risk of race conditions.  In addition you could put one after anything in the callback function that is slow (like array operations, fitting functions).

0 Kudos
Message 5 of 6
(4,050 Views)

I believe the timer callback and the com callback would normally run on the same (main) thread, so they can't really collide in that sense. It's just that you're only doing one thing or the other.  

 

You can use an async timer instead, which runs on a spearate thread (a single thread that's shared, BTW, among all async timers).

 

Looking for regular expressions is compute intensive.

 

You could set up a pool of worker threads and then when you need to parse an incoming message, hand off the task to a worker thread.  The regular expression library is thread safe I do believe - NI said it wasn't but then we looked at the source code (provided with CVI) and it looks like it is maybe 😉

 

Most windowing environments provide for two types of threads - GUI threads and worker threads.  Windows does this but NI is trying to provide an OS-neutral approach (but how many CVI users aren't using MS Windows?) and doesn't expose this as part of the windowing model when you're using in CVI.   .NET uses worker threads for callbacks on non-windows events so they avoid the problem from the get -go.

 

Usually it's desirable to keep the gui active, if for no other reason than ensuring the user can abort if she sees smoke 😉 If you want to keep her from doing things she shouldn't, you can always de-activate controls / panels while processing a previous button commit.  I sometimes set up lists of controls I want to activate / deactivate as a group for this reason.

 

It's tempting to do everything on one thread and process system events (CVI's normal programming model) but that's somewhat a simplistic approach.  I find that most effective applications with a GUI will use a thread to run the gui and worker threads to do the stuff.

 

menchar

 

 

 

 

0 Kudos
Message 6 of 6
(3,998 Views)