LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Channeled message handler: What is intented error handling

If I start a new project using the channeled message handler template. If I induce an error in "Something" frame, the Dequeue Message.vi sets channel aborted true. This leads to the Shutdown routine. No error dialog appears.

 

What is the intended way of handling errors in cmh? I couldn't find any answer on the web or this forum.

 

 

Actor Framework
0 Kudos
Message 1 of 3
(995 Views)

As someone who a number of years ago attempted to learn the Queued Message Handler from the Template that NI provided, I feel your pain!  Such a "pretty" structure, which does (after all) work, but teaches nothing!  

 

I've been using a CMH (Channel Message Handler) as a form of State Machine.  I made a Message that consisted of a Cluster with two elements:  State (which was an Enum, each element being the name of the State) and Data (which was a Variant that could handle data that needed to be transmitted from State to State, of from other asynchronous loops (such as the Event Loop that, for example, could react to a Parameter change and call the "Update Parameter" State, passing in the new Parameter for the State Machine to do whatever it needed to do with the new Data.

 

Three VIs are crucial for this model:  "Send State", one instance of which is placed on the Error Line leading into the CMH, with others being place in, say, the Event Loop, and also at the end of the Case Structure that lies just inside the While Loop of the CMH (one Case for each State).  Send State has to "ordinary" inputs, the Enum "State" on the top left input connector and the optional variant "Data" below it.  It exports the Messenger Channel out of the right top connector (getting it into a special "privileged" output, as befits a Channel Wire).  Similarly, if (at the end of a State) you can determine what the next State should be, you can put another Send State near the output edge of the Case Statement, bring the Messenger Channel over the Case and output edge of the While Loop, bring it up and over the While Loop and join it with the Channel Wire coming from the first Send State VI.

 

You also need (exactly one) Receive State, placed just inside the CMH (all these VIs sit on the Error Line, of course) and receive the State Message in its upper left input, bringing out (enum) State and (variant) Data, with State going directly to the "?" terminal of the State Machine's "Case" Statement.

 

The final critical VI (which also sits on the Error Line is the Error Handler.  It has "Messenger In" and "Messenger Out" terminals on the top center connectors, so every Send Message VI placed on the right edge of the SM (State Machine) "takes a detour" through the Error Handler.

.

So what does the Error Handler do?  [The Correct Answer is "Whatever You Tell It to Do"].  Did I mention that one of the States is named "Error"?

 

A critical feature of the Error Handler is that it "sits on the Error Line" that runs through the SM, so if any State function on the Error Line has an Error, the Error Handler's "Error In" will recognize it.  The "No Error" case is simple -- just pass the Messenger "through" the VI.  Note this is a little bit tricky, since you cannot pass a Channel Wire thoguth a Structure.  What I do is wire a Channel Reader, with a 1 ms Timeout, to a Case Statement wired to the Error Line.  The "No Error" case has an inner Case Statement wired to the TimeOut.  This is there to detect if there is a "Message In" -- if so, there will be a timeout (the True Case), meaning there is no Message to pass on, and you don't have to do anything.  However, if the State you just finished and you don't have to do anything (Message Out remains unwired).  But if State you are leaving outputs a Send Message, the Channel Reader will not TimeOut (the False case), so you just wire the Message back into a Channel Writer and pass it out.

 

So what do you do if there's an Error?  [That's the whole reason for an Error Handler, anyway ...].  The answer is "whatever you want to do".  What I usually do is the following:

  1. I create a TypeDef called Error Info, with three components:  "Payload" (a Variant that holds whatever Message was being carried by the Messenger, or an empty Variant if nothing was present, i.e. Timeout is True), a Boolean "Non-Fatal", and "Error", which gets the contents of the Error Line.
  2. I clear the Error Line.
  3. I create a new Message to pass out -- the State is "Error", and the variant Data is the Payload I just created.

So if no Error occurs, it (might) cost me 1 ms delay during a State transition, but so what?  If an Error occurs, however, I have a State that has all of the information (it has the Error as part of its Data) and can decide what to do.  Myself, I pop up a 5 second Dialog Box that show a formatted Error Message, then as I exit the Error State, I make the "next State" a Shutdown (largely because I treat all Errors as Fatal).  

 

So where does the Fatal/NonFatal decision get made?  Right now, the Error Handler has a "Non-Fatal" Boolean input that I don't wire, letting it stay False, hence All Errors are Fatal.  I haven't (yet) come across a situation with a "non-Fatal" Error, but I put it in "because NI had one in the QMH" (not a good reason ...).

 

Hope the explanation is clear.  I hope you try coding this up yourself -- you'll learn a lot faster (and better!) how to use Messenger Channel Wires to build a Better Channel Message Handler that you can understand, and that handles errors "as you want".

 

Bob Schor

 

P.S. -- if you write a small Project with TypeDefs and a small CMH and attach the Project (I refuse to look at pictures), I'll be happy to critique it. 

 

Message 2 of 3
(955 Views)

I'll give it a try and let you know, thanks so far. 

Actor Framework
0 Kudos
Message 3 of 3
(917 Views)