Building a Queue‑Based Producer/Consumer VI in LabVIEW
Step‑by‑step guide to building a LabVIEW Producer/Consumer VI that uses queues to decouple acquisition from processing, with checks, shutdown options, and limitations.
26 Aug 2025, 01:09 UTC

Desired outcome
Create a top‑level VI where a producer loop (e.g., a DAQ acquisition or instrument read) places data onto a thread‑safe FIFO queue and a separate consumer loop dequeues, processes, and logs that data. The queues decouple acquisition timing from potentially slow processing or file I/O, so the producer can maintain its sample rate without being blocked.
Prerequisites
- Familiarity with LabVIEW dataflow, While Loops, error clusters, and using clusters or typedefs for message payloads.
- LabVIEW 2020 or later (the Queue VIs are present in all recent versions; palette locations may differ slightly).
- Optional: the built‑in Producer/Consumer template (File → New → Templates → Producer/Consumer) can be used as a starting point.
Procedure
- Define the message payload
Create a strict typedef cluster that holds the data you want to pass. For example, a cluster with a timestamp (DBL) and a 1‑D waveform (Waveform) named
MsgPayload. Using a typedef ensures the same data type in every queue operation. - Obtain the queue reference once
Place an
Obtain Queuenode before the loops. Wire a constant string to thequeue nameterminal (e.g.,"DataQueue"). Set theelement typeto the typedef you created. Leavemax queue sizeunwired for an unbounded queue, or wire a numeric constant (e.g.,1000) to limit depth. Settimeoutto-1(wait forever) for now; you will adjust this later for production. - Start the producer loop
Inside a While Loop, place your acquisition code (e.g., DAQmx Read). Bundle the acquired data with any metadata into a
MsgPayloadcluster. Wire that cluster to theelementterminal of anEnqueue Elementnode. Use the same queue reference obtained earlier. Wire theerror outof Enqueue to the loop’s error shift register so acquisition stops on error. - Start the consumer loop
In a parallel While Loop, place a
Dequeue Elementnode using the same queue reference. Set thetimeoutterminal to a finite value (e.g.,1000ms) to avoid indefinite blocking if the producer fails. Wire the dequeued element to your processing or logging code (e.g., Write to Measurement File, UI update). Wire theerror outof Dequeue to the loop’s error shift register. - Wire error handling
Pass the error clusters from both loops into a Merge Errors function (or simply wire them sequentially) and connect the result to the top‑level VI’s
error outterminal. This ensures any error in either loop propagates outward. - Shutdown sequence
Choose one of two common stop strategies:
- Queue release stop: When the UI or a stop button signals termination, place a
Release Queuenode after the producer loop (or in the UI handler). Releasing the queue causes any blockedDequeue Elementto return error-1073807339(queue released), which breaks the consumer loop. - Stop‑message strategy: Define a special cluster value (e.g., a Boolean flag
stopset to TRUE) and enqueue it from the producer or UI. The consumer checks for this flag after each dequeue and exits its loop when detected.
After both loops have exited, place a final
Release Queuenode (if not already called) and verify that no error is present on the top‑level error wire. - Queue release stop: When the UI or a stop button signals termination, place a
Expected checks during development
- Run the VI with execution highlighting. You should see the producer and consumer loops advancing independently; the consumer may lag if you add a
Wait (ms)inside it. - Open
Get Queue Status(from the Queue palette) and wire the queue reference to monitornumber of elements. With an unbounded queue, watch the count grow when the consumer is slowed; with a bounded size, the count should level off at the maximum you set. - Trigger a stop (via UI button or stop‑message) and confirm that both loops exit, no error remains queued, and the queue reference is released without leaving an orphaned queue (you can reuse the same name in a subsequent run without error).
- Check the
error outof the VI after a normal stop; it should be clear (no error) unless you intentionally used the stop‑message method that returns a specific error code you defined.
Recovery and shutdown options
- Flush Queue: If the consumer stalls and you need to discard backlog, call
Flush Queueafter releasing the queue (or before, if you want to clear while still acquiring). This removes all elements without error. - Lossy enqueue: For non‑critical data (e.g., status updates), enable the
lossy? terminal onEnqueue Element. When the queue is full, new elements are dropped instead of blocking the producer. Use this only when occasional loss is acceptable. - Timeouts in Dequeue: Always set a finite timeout in production code to avoid permanent hangs if the producer fails to release the queue.
Limitations and practical verification
- Queue elements are copied; large payloads (e.g., multi‑megabyte arrays) increase memory traffic and can degrade performance. Keep payloads compact—use fixed‑size arrays, clusters, or references to data stored elsewhere.
- The pattern adds indirection; for a single‑loop task that does not need decoupling, a simple While Loop is sufficient.
- Verify on your exact LabVIEW version: open Context Help for
Obtain Queue,Enqueue Element,Dequeue Element, andRelease Queueto confirm terminal names and default values. - To test backpressure, insert a
Wait (ms)of 200 ms in the consumer loop while the producer runs at 1 kHz. Observe the queue depth withGet Queue Status; it should rise until it hits the max size (if set) then stabilize.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.