LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

How to put a CVICALLBACK in its own thread

Starting with CVI version 8.5, CVI now has UDP support.  The UDP data is received with a CVICALLBACK UDPCallback function.  I am receiving 65500 bytes at 72 Hz and some of my GUI controls are no longer responding.  How can I put the callback into its own thread?
0 Kudos
Message 1 of 7
(5,043 Views)

You could have an async timer callback poll the UDP channel for data ready periodically, and have that callback do the read.  Async timers run on their own thread.  Would have latency, unlike the read in the callback.

 

Or, create a thread pool so that when you get a data ready event callback, have the callback use one of the pool threads to do the read.  That way the callback can return to allow the main thread (user interface) to run while the worker thread from the pool does the work of reading the channel.  The UDP library should be threadsafe, it shouldn't matter what thread you do the read from.  You may not need more than one thread in the pool, depending upon how the UDP library works - it could be that the channel won't generate another callback until the read is completed - the docs on UDP lib say that channel operations are synchronous.

 

NI provides thread pool library functions I believe.

 

 

 

 

0 Kudos
Message 2 of 7
(5,015 Views)

You can create a thread and make the thread function sleep in a loop and also process events.

 

Then you can call the PostDeferredCallToThread function from the callback to pass the UDP processing "duty" to that thread function.

You need to get the thread ID from the thread function (with CmtGetCurrentThreadID) and store it in a variable.

 

Hope this helps, 

S. Eren BALCI
IMESTEK
Message 3 of 7
(5,006 Views)

I've a similar problem with TCP/IP. I've packets of 500bytes at very high rate. My TCP flux is about 10mbit/sec. Using the TCP/IP Callback to read the packets when some data is available in the queue the CPU goes to 100% and i don't know how to avoid this problem. Any suggestion?

Thanks in advice!

0 Kudos
Message 4 of 7
(4,871 Views)

A CPU at 100% is not necessarily a problem. I have CVI TCP/IP transfers at over 57MBytes/sec without difficulty. It might help if you had a separate data processing thread to handle the data that you read in a TCP callback in the main program thread, but this depends on your system design.

 

My approach was to have a Timer callback running with an interval of 0 seconds - yes this means that there is ALWAYS a pending callback waiting to be run and yes it does give a CPU utilisation of 100%. The key step is to include as the last line of the Timer callback, a call to ProcessSystemEvents(). This will ensure that any GUI controls, TCP and other system callbacks are called and serviced before the Timer callback is re-run. This approach maintains GUI responsiveness and maximises the throughput of the TCP callback mechanism.

 

JR

0 Kudos
Message 5 of 7
(4,867 Views)
Thank you for the reply. Can you explain better what are the advantages to use a timer callback when a tcp callback is continously called with such data rate? For example in my case everytime a tcp callback occours i read only one packet (500bytes) so when the tcp callback exits it is called immediately.
Message Edited by dfantoni on 01-29-2010 08:14 AM
0 Kudos
Message 6 of 7
(4,858 Views)

One of the things that ProcessSystemEvents() does is to check if any system TCP data is ready to be read, and if it is to call the TCP callback. Once inside the TCP callback, there is nothing stopping you from reading all packets that may be available, instead of just one. It may be more efficient to read as many packets as you can, before leaving the callback. Obviously if more data is still waiting to be read when you exit the callback this will be detected the next time ProcessSystemEvents() is called. The reason that simple CVI programs do not need to call this function is that it is inherently called by the run-time mechanism within RunUserInterface(), in conjunction with the CVI sleep policy settings.

 

The point about doing all this inside a permanently running Timer callback is simply to ensure that no CPU time is wasted in any CVI or system timer waiting loops, such as those which manage the sleep policy.

 

JR

0 Kudos
Message 7 of 7
(4,847 Views)