Prioritizing Parallel Tasks

You can prioritize parallel tasks by strategically using Wait (ms) functions or by changing the priority setting in the Execution Category of the VI Properties dialog box.

In most cases, you should not change the priority of a VI from the default. Using priorities to control execution order might not produce the results you expect. If used incorrectly, the lower priority tasks might be pushed aside completely. If the higher priority tasks are designed to run for long periods, lower priority tasks do not run unless the higher priority task periodically waits.

Using Wait Functions

You can use the Wait function to make less important tasks run less frequently. For example, if several loops are in parallel and you want some of them to run more frequently, use the Wait functions for the lower priority tasks. This relinquishes more time to other tasks. In many cases, using Wait functions is sufficient. You probably do not need to change the priorities by selecting File�VI Properties and selecting Execution in the VI Properties dialog box.

As described in the Synchronous/Blocking Nodes section, when a block diagram waits, the computer removes it from the queue so other tasks can run.

Wait functions are most useful in loops polling the user interface. A wait of 100 to 200 ms is barely noticeable, but it frees up the application to handle other tasks more effectively. In addition, the wait frees the operating system so it has more time to devote to other threads or applications. Consider adding waits to the less time-critical sections of block diagrams to make more time available for other tasks.

When you use the Wait (ms) function, LabVIEW waits for the amount of time you specify. When you use the Wait Until Next ms Multiple function, LabVIEW monitors a millisecond counter and waits until the counter reaches a multiple of the amount you specify.

Changing the Priorities

You also can change the priority of a VI by selecting File�VI Properties and selecting Execution in the VI Properties dialog box. You can select from the following levels of priority, listed in order from lowest to highest:

The first five priorities are similar in behavior (lowest to highest), but the Subroutine priority has additional characteristics. The following two sections apply to all of these priorities, except the subroutine level.

Priorities in the User Interface Execution System

In the user interface execution system of multithreaded applications, the execution system queue has multiple entry points. The execution system places higher priority VIs on the queue in front of lower priority VIs. If a high-priority task is running and the queue contains only lower priority tasks, the high-priority VI continues to run. For example, if the execution queue contains two VIs of each priority level, the time-critical VIs share execution time exclusively until both finish. Then, the high priority VIs share execution time exclusively until both finish, and so on. However, if the higher priority VIs call a function that waits, the execution system removes higher priority VIs from the queue until the wait or I/O completes, assigning other tasks (possibly with lower priority) to run. When the wait or I/O completes, the execution system reinserts the pending task on the queue in front of lower priority tasks.

Also, if a high priority VI calls a lower priority subVI, that subVI inherits the highest priority of any calling VI, even if the calling VI is not running. Consequently, you do not need to modify the priority levels of the subVIs that a VI calls to raise the priority level of the subVI.

Priorities in Other Execution Systems and Multithreaded Applications

Each of the execution systems has a separate execution system for each priority level, not including the Subroutine priority level nor the user interface execution system. Each of these prioritized execution systems has its own queue and two threads devoted to handling block diagrams on that queue.

Rather than having six execution systems, there is one for the User Interface system regardless of the priority and 25 for the other systems � five execution systems multiplied by five for each of the five priority levels.

The operating system assigns operating system priority levels to the threads for each of these execution systems based on the classification. Therefore, in typical execution, higher priority tasks get more time than lower priority tasks. Just as with priorities in the user interface execution system, lower priority tasks do not run unless the higher priority task periodically waits.

Some operating systems try to avoid this problem by periodically raising the priority level of lower priority tasks. On these operating systems, even if a high priority task wants to run continuously, lower priority tasks periodically get a chance to run. However, this behavior varies from operating system to operating system. On some operating systems, you can adjust this behavior and the priorities of tasks.

The user interface execution system is single-threaded. The user interface thread uses the Normal priority of the other execution systems. So if you set a VI to run in the Standard execution system with Above Normal priority, the user interface execution system might not run, which might result in a slow or non responsive user interface. Likewise, if you assign a VI to run at Background priority, it runs with lower priority than the user interface execution system.

As described earlier, if a VI calls a lower priority subVI, that subVI is raised to the same priority level as the caller for the duration of the call.

Subroutine Priority Level

The Subroutine priority level permits a VI to run as efficiently as possible. VIs that you set for Subroutine priority do not share execution time with other VIs.

When a VI runs at the Subroutine priority level, it effectively takes control of the thread in which it is running, and it runs in the same thread as its caller. No other VI can run in that thread until the subroutine VI finishes running, even if the other VI is at the Subroutine priority level. In single-threaded applications, no other VI runs. In execution systems, the thread running the subroutine does not handle other VIs, but the second thread of the execution system, along with other execution systems, can continue to run VIs.

In addition to not sharing time with other VIs, subroutine VI execution is streamlined so that front panel controls and indicators are not updated when the subroutine is called. A subroutine VI front panel reveals nothing about its execution.

A subroutine VI can call other subroutine VIs, but it cannot call a VI with any other priority. Use the Subroutine priority level in situations in which you want to minimize the overhead in a subVI that performs simple computations.

Also, because subroutines are not designed to interact with the execution queue, they cannot call any function that causes LabVIEW to take them off of the queue. That is, they cannot call any of the Wait, GPIB, VISA, or Dialog Box functions.

Subroutines have an additional feature that can help in time-critical applications. If you right-click on a subVI and select Skip Subroutine Call if Busy from the shortcut menu, the execution system skips the call if the subroutine is currently running in another thread. This can help in time-critical loops where the execution system safely skips the operations the subroutine performs, and where you want to avoid the delay of waiting for the subVI to complete. If you skip the execution of a subVI, all outputs of the subVI become the default value for the indicator on the subVI front panel.