Queued Message Handler Template documentation

Publish Date: May 22, 2017 | 7 Ratings | 3.29 out of 5 | Print | Submit your review

Overview

The Queued Message Handler (QMH) template facilitates multiple sections of code running in parallel and sending data between them. Each section of code represents a task, such as acquiring data, and is designed similarly to a state machine. Because of this design, you can divide each task into states.

Table of Contents

  1. Example
  2. Developer Walkthrough
  3. System Requirements
  4. Use Cases
  5. Overview
  6. Running This Template
  7. Modifying this Template
  8. Important Information

The QMH template is a version of the Producer/Consumer design pattern, where the user interface (producer) produces messages and the tasks (consumers) consume them. However, in the QMH template, you also can produce messages from a consumer loop.

This template includes one producer loop and one consumer loop. You can add consumer loops as needed.

 

1. Example

Refer to the Continuous Measurement and Logging sample project, available from the Create Project dialog box, for an example of adapting this template to a measurement application.

 

Back to Top

2. Developer Walkthrough

See a developer walkthrough of the Queued Message Handler template.

 

Back to Top

3. System Requirements

LabVIEW Base, Full, or Professional Development System

 

Back to Top

4. Use Cases

The QMH template is useful for applications where multiple tasks occur in parallel, often at different rates. For example, consider an application that continuously acquires, logs, and displays two signals: an RS-232 signal and an analog signal. These signals occur at different rates, so the application must have two loops that run in parallel. In addition, each loop is divided into the following states:

  • Initialize the data acquisition hardware
  • Acquire data
  • Log the acquired data to disk
  • Display the acquired data in a waveform chart
  • Set the hardware to a safe state
  • Stop the data acquisition and shut down the hardware

The application requires a responsive user interface; that is, users should be able to click buttons even while the application is executing another command. Therefore, the application requires a third parallel loop that continuously monitors the front panel for events, such as the following commands:

  • Start RS-232 acquisition
  • Stop RS-232 acquisition
  • Enable RS-232 logging
  • Disable RS-232 logging
  • Start analog data acquisition
  • Stop analog data acquisition
  • Enable analog data logging
  • Disable analog data logging

The QMH template provides a starting point for writing this kind of application.

 

Back to Top

5. Overview

This template repeatedly executes the following steps:

  1. A user interacts with the front panel, causing the Event structure in the Event Handling Loop (EHL) to produce a message. LabVIEW stores the message in a queue.
  2. The Message Handling Loop (MHL) reads a message from the message queue, removing the message.
  3. The message is a string that matches one of the subdiagrams of the Case structure in the MHL. Therefore, reading the message causes the corresponding subdiagram of the Case structure to execute. This subdiagram is called a message diagram because it corresponds to a message.
  4. Optionally, the message diagram produces another message, storing it in the message queue.

Notes:

  • The EHL is the producer loop. The MHL is the consumer loop. These loops run in parallel and are connected by the message queue, which facilitates communication between the loops.
  • The message queue is a LabVIEW queue that stores messages for consumption. Because the EHL sends messages to this queue and not directly to the MHL, the EHL can produce messages while the MHL is not consuming them. Each message queue belongs to a single MHL.
  • Every iteration of the MHL reads the oldest message in the message queue and then executes the corresponding message diagram. Although the MHL primarily consumes messages, it also can produce them.
  • Your application can have multiple MHLs. Each MHL corresponds to a task the application performs, such as acquiring or logging data.
  • Notice the UI Data cluster in the above diagram. This cluster is data that each message diagram in an MHL can access and modify. In this template, the cluster is defined as a typedef, UI Data.ctl. Each typedef belongs to a single MHL.

 

Back to Top

6. Running This Template

  1. In the Project Explorer window, open and run Main.vi.
  2. Click the front panel controls and watch the Display indicator display messages.

 

Back to Top

7. Modifying this Template

Determining Your Needs

The following table summarizes the design decisions you must make when modifying this template:

Design Decision Example Detailed Information
You need to determine how many MHLs to add. Each MHL defines a task that executes in parallel with other tasks. You have an application that acquires data and, in parallel, logs this data to disk.

This application consists of two tasks: data acquisition and data logging. Therefore, you need two Message Handling Loops.
Creating a Message Handling Loop
For each MHL, you need to determine what message diagrams to add.

A message diagram is a subdiagram of the Case structure in an MHL. Each subdiagram corresponds to a state the task can be in; therefore, to determine the message diagrams to add, separate each task into states.
You want to separate the data acquisition task into three states: Initialize, Acquire Data, and Exit. Therefore, create these message diagrams in the MHL that acquires data.

You want to separate the data logging task into three states: Initialize, Log, and Close. Therefore, create these message diagrams in the MHL that logs data.
Creating a Message Diagram
You must determine what data the message diagrams of an MHL need. Each message diagram of the data acquisition MHL needs access to a hardware reference. The Initialize message diagram needs to open this reference, the Acquire Data diagram uses this reference to acquire data, and the Exit message diagram closes the reference. Defining Data that a Message Handling Loop Needs
You need to determine when to execute each message diagram. A message diagram executes after its MHL receives the appropriate message. Therefore, you need to determine when to send each message to the MHL. You can send a message from a front panel control or from a message diagram. You want to add a button that sends the Initialize message to the data acquisition MHL.

You then want the Initialize message diagram to send the Acquire Data message to the same MHL.
Adding a Control that Sends a Message to a Message Handling Loop or Sending a Message to a Message Handling Loop, depending on whether you want a control to send the message.
You need to determine if you want the Exit message to stop each MHL. The Dequeue Message VI uses this message because it is able to shut down an MHL. You want each MHL to shut down when it receives the Stop message instead of the Exit message. Changing the Message that Stops a Message Handling Loop
When reading messages from the message queue, you need to determine if you want to ignore any specific errors. When reading messages from the message queue, you want to ignore network timeout errors. Ignoring Errors when Reading From The Message Queue

 

Creating a Message Handling Loop

A Message Handling Loop (MHL) represents a task the application can perform, such as acquiring data or logging data, in parallel with other tasks. Each MHL can be divided into sub-tasks that correspond to states. MHLs consist of the following components:

  • A message queue
  • A While Loop that reads messages from the message queue
  • A Case structure that contains a subdiagram, also known as a message diagram, for each possible message that can be read, where each message corresponds to a state of the task
  • (Optional) Data that each message diagram of the MHL can access

Complete the following steps to add an MHL:

  1. This template contains a typedef that defines the cluster that holds the refnums for all message queues. By default, this typedef has space for only one queue. Complete the following steps to add a second queue to this typedef:
    1. In the Project Explorer window, open Message Queue.lvlib:Create All Message Queues.vi.
    2. Right-click the All Message Queues constant and open the typedef:



      LabVIEW launches the Control Editor window.
    3. Expand the border of the Message Queues cluster.
    4. Duplicate the UI queue refnum in the cluster.
    5. Name the new queue refnum. For example:

    6. Select File»Apply Changes and close the Control Editor window. The Message Queues typedef now contains an additional message queue.
  2. Modify Create All Message Queues.vi to execute the following steps:
    • Obtain the message queue reference
    • Bundle this queue into the Message Queues out cluster
    • (Optional) Send an initial message to the new MHL

    The following screenshot shows an example of code that accomplishes the above steps:

  3. (Optional) If the MHL needs access to data, create a typedef that represents this data.
  4. In Main.vi, create the Message Handling Loop that represents the task:



    Notes:
    1. Recall that in step 2, you bundled the New Task queue refnum into the Message Queues out cluster. The code above shows where this cluster is unbundled and how the wire branch for the New Task queue goes to the New Task MHL.
    2. Recall that in step 2, you had the option to send an initial message to the message queue. The code in step 2 shows the initial message Initialize. The code above shows the message diagram (Initialize) that executes when this message is received.
    3. Recall that in step 4, you had the option to create a typedef. The code above shows how you wire this typedef, New Task Data, so the MHL can use it.
    4. If you want the new task to send messages to the UI queue, branch the wire for the UI queue refnum into the New Task loop.
    5. The code above shows the FALSE constant wired to the conditional terminal of the While Loop. In each MHL, only one message diagram should be able to stop the MHL. This design prevents accidental and partial shutdowns by guaranteeing the following conditions:
      • Shutdown code runs only right before the MHL shuts down.
      • Shutdown code always runs to completion.
    6. To keep the block diagram of Main.vi compact and readable, you can encapsulate each MHL into a subVI. To further organize the project, you can put each subVI, any supporting VIs, and its data typedef into a project library. Refer to the Continuous Measurement and Logging sample project, available from the Create Project dialog box, for an example of this design.
    7. The MHL shown above does not need access to the Stop Event wire. The MHL in the template uses this wire to execute the Fire User Event - Stop VI, which shuts down the Event Handling Loop. No other MHL needs to do this.
  5. Add message diagrams to the Case structure in the MHL. To minimize errors and unexpected behavior, ensure each MHL has the following message diagrams:
    1. A message diagram that initializes the task; for example, this diagram could connect to a hardware device, open files for data logging, and so on.
    2. A message diagram that handles unrecognized messages.
    3. A message diagram that, when executed, releases the message queue and stops the loop. For example:



      By default, the message that triggers this message diagram is Exit, but you can change this.
    4. (Optional) If the application requires that the MHL stop performing its task but stay active (to potentially restart the task), create a message diagram that uses the Flush Queue function to remove any pending messages.

      For example, in a continuous measurement application, you may have Start Measurement and Stop Measurement buttons. Clicking Start Measurement initiates the MHL, which continues execution by sending itself the same message continually. In this application, clicking Stop Measurement should not only stop the measurement but also flush the message queue without stopping the MHL. If you do not flush the message queue, clicking Stop Measurement will have no effect. The message queue contains more messages to continue the measurement, and each of these messages causes another message of its kind to be produced.
  6. Add code to the EHL that instructs the new MHL to stop in the event of an error or when the application stops; that is, execute the message diagram you created in step 5c. Add this code to the Event Structure and Error case shown in the following figure:

  7. Send messages to the MHL.

 

Creating a Message Diagram

A message diagram is the subdiagram of a Case structure, located in a Message Handling Loop, that handles a particular message. It is similar to a state in a state machine.

A message diagram is a subdiagram of a Case structure that is labeled with a string. It executes when the MHL receives a message that matches this label.

Complete the following steps to create a message diagram:

  1. In the MHL that represents the task, add a subdiagram to the Case structure.
    Tip   If you are adding a message diagram to the MHL included in the template, you can automatically include the data and error wires in the new message diagram by duplicating the ---Copy This Frame--- case.
  2. In the case selector label, enter the text of the message that will trigger this message diagram to execute. For example, the following message diagram executes when LabVIEW reads New Message from the message queue:

  3. Add code that executes upon receiving this message. As you do this, pay attention to the following guidelines:
    • To access and modify task data, use the Unbundle By Name and Bundle By Name functions:

    • To ensure that you track all errors, use the Merge Errors function to merge errors coming from all nodes in the subdiagram.
    • To access message data, wire the Message Data input tunnel to a Variant to Data function:

    • To send a message to a message queue, use the Enqueue Message VI.
  4. To execute the message diagram, send a message to the MHL. The message you send must match the label of the message diagram that you entered in step 2.

 

Defining Data that a Message Handling Loop Needs

In the template, UI Data.ctl is the typdef that defines the cluster of data that the MHL can access:

Modify this typedef according the needs of your application. For example, if more than one message diagram in an MHL needs to modify the same Boolean control, add a Boolean control to this typdef.

If you have more than one MHL, create a typedef for each one. This design prevents errors by ensuring one MHL cannot access the data of another.

 

Adding a Control that Sends a Message to a Message Handling Loop

  1. Add a control to the front panel.
  2. (Optional) If you want a message diagram to programmatically modify this control, bundle the control refnum into the typedef for that MHL.
  3. Add an Event case to the Event structure in the Event Handling Loop.
  4. Configure the event to trigger when the value of this new button changes:

  5. Click OK. LabVIEW creates an event case in the Event structure.
  6. Associate the terminal with the event by dragging the block diagram terminal for the new control inside this event case.
  7. Add code to this event case that sends a message to an MHL.

 

Sending a Message to a Message Handling Loop

Messages are strings that instruct an MHL to execute one of its message diagrams. Messages are produced by the EHL and are stored in the message queue. Every iteration of the MHL reads the oldest message in the message queue and executes the corresponding message diagram.

Complete the following steps to send a message to an MHL:

  1. Decide what part of the application will send the message and which MHL will receive the message. You can send messages from the EHL or from a message diagram.
  2. Decide what message diagram will execute when the MHL receives this message. Ensure the message diagram exists and has the same name as the message you want to send. If the message diagram does not exist, create it.
  3. In Main.vi, access the wire that represents the message queue of the receiving MHL. You access this wire by unbundling it from the Message Queues out cluster that is returned from the Create All Message Queues VI. Main.vi already contains the following code that unbundles the UI queue refnum:



    Expand this Unbundle by Name function to access the wires of message queues for all MHLs.
  4. In the part of the application that will send the message, create the following code:



    In the code above, Message is the text that matches the message diagram you identified in step 2, and the message queue refnum is the wire you identified in step 3.
    Note  Access the Enqueue Message VI from the Project Explorer window of the template or by using Quick Drop.
  5. (Optional) To specify that this message supersedes others already in the queue, wire TRUE to the Priority Message? input of the Enqueue Message VI:



    High-priority messages are typically reserved for emergency stop situations. These messages are placed at the front of the message queue, guaranteeing that the receiving MHL will consume that message next.
  6. (Optional) To send data with the message, wire a value to the Message Data input of the Enqueue Message VI. This terminal can accept any data type. For example, the following code sends a double-precision floating-point number along with the message:



    LabVIEW displays a coercion dot on the input terminal because the data type of this terminal is variant.

 

Changing the Message that Stops a Message Handling Loop

Messages are strings, meaning you can create or change a message without modifying a typedef. However, this template defines one message: the Exit message is defined in Message Queue.lvlib:Dequeue Message.vi:

If you want your MHLs to shut down on a message other than Exit, change the message in this VI.

 

Handling Unrecognized Messages

Ensure all Case structures in an MHL have a Default message diagram. The code in this message diagram executes when the MHL reads a message that does not have a corresponding message diagram. Having a Default message diagram is important because messages are strings that you enter while programming, not values you select from an enum.

 

Ignoring Errors when Reading from the Message Queue

  1. In the Project Explorer window, open Message Queue.lvlib:Dequeue Message.vi and display the block diagram.
  2. Find the Case structure nested inside the Error case:

To ignore errors when reading from the message queue, add error codes to the case selector label of the nested Case structure. The errors to ignore depend your application. For example, if you are reading the queue over a network, you might want to ignore timeout errors.

 

Enabling a Message Handling Loop to Programmatically Modify Controls and Indicators

To enable an MHL to modify a control programmatically, create a refnum for the control and bundle it into the typedef that stores data for that MHL. The following procedure uses UI Data.ctl as an example.

  1. Create the control refnum and move it into the Initialize subdiagram of the MHL.
  2. Open UI Data.ctl and add space for the refnum to the cluster.
  3. In the Initialize subdiagram, expand this new terminal on the Bundle by Name function and wire the control refnum to it:

The refnum for this control now is available to any message diagram that has access to UI Data.ctl. For example, the following code shows the Disable Button message diagram, which uses the control refnum to disable and gray out the front panel button:

 

 

Back to Top

8. Important Information

Copyright

© 2012 National Instruments. All rights reserved.

Under the copyright laws, this publication may not be reproduced or transmitted in any form, electronic or mechanical, including photocopying, recording, storing in an information retrieval system, or translating, in whole or in part, without the prior written consent of National Instruments Corporation.

National Instruments respects the intellectual property of others, and we ask our users to do the same. NI software is protected by copyright and other intellectual property laws. Where NI software may be used to reproduce software or other materials belonging to others, you may use NI software only to reproduce materials that you may reproduce in accordance with the terms of any applicable license or other legal restriction.

End-User License Agreements and Third-Party Legal Notices

You can find end-user license agreements (EULAs) and third-party legal notices in the following locations:

  • Notices are located in the <National Instruments>\_Legal Information and <National Instruments> directories.
  • EULAs are located in the <National Instruments>\Shared\MDF\Legal\license directory.
  • Review <National Instruments>\_Legal Information.txt for information on including legal information in installers built with NI products.

Trademarks

LabVIEW, National Instruments, NI, ni.com, the National Instruments corporate logo, and the Eagle logo are trademarks of National Instruments Corporation. Refer to the Trademark Information at ni.com/trademarks for other National Instruments trademarks.

Other product and company names mentioned herein are trademarks or trade names of their respective companies.

Patents

For patents covering the National Instruments products/technology, refer to the appropriate location: Help»Patents in your software, the patents.txt file on your media, or the National Instruments Patent Notice at ni.com/patents.

 

Back to Top

Bookmark & Share


Ratings

Rate this document

Answered Your Question?
Yes No

Submit