Multithreading in LabVIEW Real-Time


This document explains multithreading in LabVIEW, including execution priorities, the user interface thread, and time-critical sleep mode.


General Execution System Knowledge

In LabVIEW, events are prioritized, where events with higher priority execute first.

Normal Priority allows the CPU to be shared between threads. So, the embedded CPU will share time with your LabVIEW Real-Time VI and with the user interface thread or any other threads you may have going.

Time-Critical Priority gives 100% of the CPU time to the time-critical thread. The issue is that you must not starve the system of CPU time if you plan to have anything else going on, such as a user interface thread or TCP/IP communication. A time-critical loop, which does not have any sleep time, will completely monopolize the embedded CPU resources. Sleep time is implemented using the Wait or the Wait Until Next ms Multiple functions, which look like a stopwatch or a metronome, respectively. A common technique to determine the amount of necessary sleep time is to target a VI to the LabVIEW Real-Time Series hardware. In this mode, the embedded VI only needs to allow enough time for VI Server or TCP/IP communication to send and receive information from the host application. Also, during development, it is a good idea to set your programs to a lower priority.

Subroutine Priority is the highest priority level. When you give a VI subroutine priority, it in effect takes control of the thread in which it is running. No other VI can run within this thread. That means that if you give a subVI subroutine priority in your time-critical thread, no other tasks will be performed within the time-critical thread. If the time-critical thread has a user interface component, then no updates will be made to the UI while the subVI is running. You can use this priority level to permit a VI to run most efficiently. In order to fully understand priorities, an understanding of the LabVIEW execution system is key. Refer to the LabVIEW Software Page for more information.

The User Interface Thread

When you run a VI with the LabVIEW Real-Time Development System, the front panel of the embedded VI is open, and controls and indicators are updated by a user interface thread, which must be maintained between the host machine and the block diagram code running on the RT target. Please refer to the link below for a discussion on LabVIEW Real-Time architecture. If your VI priority is set to normal, the block diagram will share time with the user interface thread. This may or may not pose a real-time problem for you depending on your application requirements, because front panel interactions have the same priority as your code. Thus, front panel interactions may disturb real-time performance. However, if your VI priority is set to time-critical, the user interface thread may be starved of processor time causing your front panel to appear locked up.

Adding wait time to the diagram will assure determinism by putting your time-critical block diagram “to sleep” and allowing the user interface thread to update the front panel periodically. However, the best method for achieving a high-performance, fast real-time application is to have an embedded VI that displays no user interface and a LabVIEW Real-Time VI (Instance A) that runs on the Host PC. The Host LabVIEW Real-Time application can communicate with a communication application running on the host using standard network techniques (VI Server and TCP/IP). However, when application speed is important, using Peek and Poke type subVIs to access the PCI/PXI 7030 shared memory directly will give you the best performance.

See Also:
LabVIEW Real-Time Architecture and Good Programming Practices

Time-Critical Thread Sleep Mode

As we have seen, the user can introduce sleep time to an application by calling the Wait or Wait Until Next ms Multiple functions. Inside a loop, these two VIs can be especially effective. However, great caution must be used when introducing sleep time to VIs running with time-critical priority. The LabVIEW Real-Time Execution System puts the entire thread to sleep; therefore, all VIs on the same time-critical thread go to sleep, even if only one is actually put to sleep during execution. Furthermore, if within a single time-critical VI, there are several parallel loops, all loops will sleep if any one loop is put to sleep. Refer to the illustrations below.

The illustration above shows two different VIs, and, each with a while loop and sleep modes of 200 ms and 20 ms per iteration. If they are both set for time-critical priority in the same execution system, both will sleep for the same amount of time. That is to say even though should sleep one-tenth as much as, it will actually sleep as much as because all VIs on the time-critical thread are put to sleep if a single time-critical VI sleeps! Therefore, not only will sleep 200 ms per iteration, but it will also sleep 20 ms every time iterates. The same is true for The next illustration below is very similar to the first illustration, except now the two loops are in the same VI. The behavior, however, is the same; when one loop sleeps, the other loop will sleep too if the Two is set for time-critical priority.

The way around this is to put the two loops in separate VIs and give each VI a different time-critical thread by assigning each VI their own execution system (such as standard, instrument I/O, data acquisition, and so on). However, for true determinism, the user should only have one time-critical loop ever running in LabVIEW Real-Time. Also, only time-critical threads running on embedded LabVIEW Real-Time processors experience this global sleeping effect. This is not the case for time-critical threads running on non-LabVIEW Real-Time operating systems, such as Windows, Unix, and so on.

Was this information helpful?