LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

When is producer/consumer not suitable for separating UI/Logic?

Solved!
Go to solution

Ok, I tested it with 2016 and 8.2 and it does indeed work with that error.  Yes, the documentation is wrong.  A pleasant surprise.

 

Now I just wish I had 2012 installed to see if I could figure out what I remember happening.  It might have been a state machine issue where if there was an error the state with the Unset Busy would not be called.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 11 of 16
(2,614 Views)

@crossrulz wrote:

Ok, I tested it with 2016 and 8.2 and it does indeed work with that error.  Yes, the documentation is wrong.  A pleasant surprise.

 

Now I just wish I had 2012 installed to see if I could figure out what I remember happening.  It might have been a state machine issue where if there was an error the state with the Unset Busy would not be called.


Somewhere around that time I think they also changed the way certain queue functions handled errors, also.  I forget which ones.  Destroy Queue, maybe?

Bill
CLD
(Mid-Level minion.)
My support system ensures that I don't look totally incompetent.
Proud to say that I've progressed beyond knowing just enough to be dangerous. I now know enough to know that I have no clue about anything at all.
Humble author of the CLAD Nugget.
0 Kudos
Message 12 of 16
(2,593 Views)

@DoctorAutomatic wrote:

Literally, I can't recall ever reading an argument against it. 


Then you never met me... You should use a PC when you need a PC. Use a SM when you need a SM, use a QMH when you need a QMH. I've seen good uses of PC, but I've also seen programs crash because the PC was parallelizing the tasks while they should be sequential. Separating UI isn't always good, sometimes the UI needs to be blocked until a task is done. What is worse, I've seen about dialogs being implemented with PC, because it "was the template". That "one size fits all" mentality is not good.

 

What I've noticed with PC is that often all program logic is programmed in the main. That's not something specific to PC, but people using PC seem to be inclined to do so. It's probably because PC is used as an introductory template... This kind of programming is terrible for reusability. It is easy to make huge PC one-liners, where everything is in one big VI...

 


@DoctorAutomatic wrote:

However, as I think about a part of a project I'm doing, I feel this is not the behavior I want. But it feels like I must not be thinking right given all this prior reading.


I don't remember the last time I've used a PC. I usually go for some event driven architecture. Not this isn't that different from a PC, there are still processes producing events, and processes consuming the events. You'll always going to need that for non-trivial programs. It's different from PC template because with the typical PC, P and C are usually on the same diagram, and there is a one-to-one stream of events. Also traditional PC use queues, not events. The events enable many-to-many streams of events, something I usually want.

 

You should thing about what you need. Don't pick a template simply because "it always does the job". You want to use the simplest possible (not simpler) architecture that does the job for your application. Experience with the architecture is a factor, but you should not be afraid to take a leap into the unknown. Failure isn't a bad thing (that's why there is SCC). As long as the rest of the program is modular, it should not take that long to switch from one architecture to another.

Message 13 of 16
(2,584 Views)

I feel like I need to hammer in some concepts here since there tends to be some subtle differences most LabVIEW programmers don't catch and it will cause confusion.  These are usually missed since most LabVIEW programmers do not have a CS background (myself being an Electrical Engineer).

 

Producer/Consumer is a concept of offloading a specific task to a separate loop for parallel processing.  This data is homogeneous (single data type) and is set up for performance.  The classic example here is a DAQ loop sending readings to another loop for logging purposes.  These two loops are typically highly coupled (dependent on each other).

 

A Queued Message Handler (QMH) is a loop that accepts messages from other loops and reacts to these messages.  The message usually contains the message ID/name and the data associated with that message.  This is what most people use to separate the UI from the logic.  The classic example being the Model-View-Controller architecture.  If you want to really dive into a CS thought process, the Actor Framework is based on the QMH.  The loops involved here are set up to have low coupling (easy to take a QMH and just use it in another application).

 

So when was the last time I used a Producer/Consumer?  Probably back in 2012 or 2013.  I had a setup where I had the producer loop reading the data from a file and a consumer loop processing that data.  This gave me about a 2x performance improvement.  Going back further, I had about 5x improvement in performance over somebody else's less data processing and mine processing was a lot more involved (theirs was a simple convert to a float where I had to do a bunch of bit manipulations, scaling, etc to build up a cluster), most of that gain was from the Producer/Consumer.

 

QMHs I used to use all the time.  I had QMHs for instruments, data logging, data processing, UI, network communications, etc.  Everybody to send a message to anybody else using an API that I made for sending a message each QMH.

 

But as wiebe stated, use the right tool for the right job.  My current job does not require a PC or QMH, so I have not used either for some time now.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 14 of 16
(2,570 Views)

@billko wrote:

@Blokk wrote:

There are quite a few properties/methods that can take 0.5seconds all the way up to 4-5seconds to return. I can't imagine wanting the desired behavior to be a user clicking around and queuing up a bunch of other commands while the first is still waiting to return.

 

I never met a single case when a producer-consumer (any sort of) was not appropriate to fulfil my application requirements. I disagree that the "set busy", "unset busy" is a good method to use during a certain state is still running in your application. I only use these "busy" functions to indicate to the user that some sort of initialization step is running (like VISA init + device ID check, etc), and these usually do not take more than a couple of seconds. And be aware, there is a danger when you use the "busy" functions! Imagine, you put your "busy" function on the same error wire, and something triggers an error before the "unset busy"! Your "unset busy" will be not executed (default error in functionality), so your user will be doomed 🙂 So branch the error wire before the "unset busy", and put a "erase error" before it.

 

But as I said, I would never use the "busy" functions for longer running tasks! When I want to stop the user to "clicking around", and enqueue (or putting new msgs on the Channel wire) undesired commands, I just use property nodes to temporary disable those buttons which the user should not interact with! This gives you much more flexibility, since certain functions should be still accessible even during longer ongoing tasks! Like "abort" functions, or imagine multiple Consumer loops!

One of my most often used subVIs is an "enable/disable" one. You can select all your Boolean controls in your app, and create all their references at once. After this just bundle them up into a cluster wire, so you can get the required button refs anywhere in your code from a single wire, using "unbundle by name"! I often need to enable/disable multiple buttons in my application at once, then I like to use a subVI with control refnums as an array input:

 

enable_.png

 

EDIT: so I would say, if a step takes less than 2-3 seconds, I would go for the "busy" functions, and for any longer times, I would go for the property nodes (temporary disabled and grayed out)...


I am in agreement here.  If it's more than a few seconds, take the time to disable and grey out the controls you don't want the user to interact with.  If there are buttons that are commonly set together, you can make a subVI to enable or disable them at once.  This has the added flexibility of having a way of exiting that state or closing the application if something goes wrong.  My rule of thumb is, "always give the user an exit strategy."


I'm in agreement as well with both your takes on this. The tasks I'm talking about never take more than a few seconds. I don't want a bunch of commands queuing up while busy because this is a driver test panel for multiple robotic arms hanging from the same gantry rails, the least desireable outcome is a bunch of unexpected movements or crashes. So I set the cursor busy in this case. At least for now. There are so many types of commands for this thing that the test panel has a lot of controls/indicators, so many that I don't feel like conditionally enabling/disabling different combos of them for every circumstance.

 

Ironically, I'm likely (no, almost certainly) to be the only user of this test panel and I know every last quirk of the robotic system it's interacting with and of course how my driver interacts with it. I guess I sort of view this desire to make the test panel "user friendly" or "outward/client" facing as a learning opportunity because when it comes down to it, I of course know not to queue up a bunch of random commands.

0 Kudos
Message 15 of 16
(2,465 Views)

wiebe@CARYA wrote:

@DoctorAutomatic wrote:

Literally, I can't recall ever reading an argument against it. 


Then you never met me...


Or me.   I would argue against anyone using the NI templates where the event-loop is a "Producer".   It is a worst-of-both-worlds compromise between a closely-integrated UI and a fully-developed separated UI.

0 Kudos
Message 16 of 16
(2,451 Views)