LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Implementing multiple vi's in a subpanel in a Queued Message Handler project

Solved!
Go to solution

Hello,

I am using a queued message handler architecture to run various processes in parallel. I would like to load multiple vi's onto the main vi's front panel using a subpanel. I used the Multiple VI's in a Subpanel example as a base. Attached is the PNG of my display loop (I'm not sure I can upload the whole project because it contains at least fifty subvis).

 

The display message queue is the input to a case selector and inside each case, the next vi to display is sent to the message queue. Each vi is listed in an enum array just as it is in the example.

However, I keep getting error 1000 with the run vi method. By watching the vi run with highlight execution, I see that the vi never goes into the while loop to get removed before the next one tries to get loaded.

 

Is there a better way of doing this? I really feel like this method is fundamentally wrong, I am just not sure which direction to go. Im still new to Labview so any pointers or advice would help!

0 Kudos
Message 1 of 7
(2,640 Views)

@bbell wrote:

Hello,

I am using a queued message handler architecture to run various processes in parallel. I would like to load multiple vi's onto the main vi's front panel using a subpanel. I used the Multiple VI's in a Subpanel example as a base. Attached is the PNG of my display loop (I'm not sure I can upload the whole project because it contains at least fifty subvis).

 


To upload a Project with hundreds of VIs, compress the Folder that contains them all and upload the resulting single .ZIP file.

 

I've had no problem running 48 VIs and having pairs of them appear in two sub-Panels.  Here are some questions that we could figure out for ourselves if you attached your entire Project, but which you should be able to answer --

  • Do you start all of your VIs more-or-less at the same time, and just choose which one is displayed in the sub-Panel?
  • Is there any relationship between "seeing a sub-VI in the Front Panel" and "running the sub-VI"?  That is, do you either start the sub-VI when being selected or stop the sub-VI at the same time you stop viewing it, or are these events unrelated?
  • Note that the above two points are "weakly related" ...

Incidentally, I tend to run independent sub-VIs as Asynchronous sub-VIs using Start Asynchronous Call.

 

Bob Schor

0 Kudos
Message 2 of 7
(2,605 Views)

Stopping the VI's with Abort is quite violent, you should send an Event or Queued message. As Bob mentions Start asychronous call can be a better choice, especially if you want to attach some inputs. (you can use Set Control Value, but all in all it's Messier).

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 3 of 7
(2,591 Views)

Hi Bob,

Thanks a lot for your help.

 

-I only want one vi to show on one subpanel on the main vi at a time.

-I only want the vi to both start running and appearing when called. However, if I understand the code correctly, the vis are all running at the same time and only the chosen one is displayed. I changed the original example so that it aborts before the next one is loaded. I have simplified it into its own vi and attached it to give you a better understanding.

-Using asynchronous calling is good for when you do not need the results of the subvi immediately. However, some of the data from a vi will be needed for the subsequent vi running on the subpanel. Would I use an asynchronous call and collect option? Or global/shared variables? Or queues?

 

Thank you for your time, I really appreciate it

bbell

 

 

0 Kudos
Message 4 of 7
(2,584 Views)

Hi Yamaeda,

 

Thank you for your time!

Could you give me a bit more insight on sending a Queued message to stop a vi in lieu of Abort vi? Would this message be sent from the vi itself or would it be sent in the event case (for example, when NEXT is pressed, the stop vi queued message would be sent?). In either case, what function would I use to actually stop the vi since the queued message tells the program what to do but not how, if I understand correct.

 

bbell

0 Kudos
Message 5 of 7
(2,578 Views)
Solution
Accepted by topic author bbell

You can Have Your Cake and Eat It, Too! by taking advantage of "Message Queues" in your design.  Without worrying about the Particulars of your tasks, here is what I would recommend:

  • I'm assuming that each Task can run independently, simultaneously, will be "controlled" (i.e. Started and Stopped, and maybe "adjusted" during running) by the Main VI, and that the Main VI can (independently) choose which Task's Front Panel will appear in a sub-Panel.
  • For simplicity, I'm going to assume the Tasks respond to only two Commands, Start and Stop.
  • I'm going to assume that the Tasks may need to "push" data back to the Main VI while they are running, even if they are not running in a sub-Panel.
  • I would build two Queues for each Task, Host-to-Task and Task-to-Host.  Note that it is much simpler if all Tasks can use the same TypeDef for the Queue contents, as the Host needs to maintain a pair of Queues for each Task (and it is simpler if they can be placed in an Array of Queues, which is the structure I use).  Indeed, you can send each task a Queue Cluster with Host-to-Task and Task-to-Host Queue References, saving a Connector element and simplifying wiring.
  • Recall I'm assuming all Tasks run all the time -- adjust this section if you want them to run one-at-a-time, stopping one before starting another.
  • Using a For Loop, set each Task running using Start Asynchronous Call.  Generate its Queue Cluster and wire it, and its other required Inputs (which should be initialized, unless you also want to pass them in as Messages, in which case you need something like a Queued Message Handler, an even more flexible structure).
  • When you are ready to start Task 1, put "Start" into the Host-to-Task Queue for Task 1.
  • When you want to view Task 1's Front Panel, put its VI Reference (which you got two steps previously) in the Open SubPanel Method.  Note you can do this before or after you Start the Task.
  • If Task 1 is expected to send data back to the Host, the Host needs to monitor the Task-to-Host Queue for Task 1.
  • Whenever the Host wants to Stop Task 1, it sends the Stop Message to the Task.
  • Note that if the Task is supposed to do things in a loop, you'll probably want to give it some additional States/Messages, such as "Run", that get it to do a Loop's worth of stuff (and sends itself another Run message when the Run case finishes, depending on Stop getting "between" the Run calls to stop it safely).
  • Similarly, the Host can turn off viewing of Task 1 whether or not the Task is running.  Viewing and Running are'  totally independent.

This sounds more complex, but it is really simple, works really well, and even works in an Executable (without changing anything).  There is a potential drawback (some might find this an advantage) -- my preferred method of handling Start Asynchronous Calls keeps all of the Tasks' code in memory, loading it when the Main VI runs, so if Memory is a precious commodity, this might be a consideration.

 

Bob Schor

0 Kudos
Message 6 of 7
(2,573 Views)

@bbell wrote:

-I only want one vi to show on one subpanel on the main vi at a time.

-I only want the vi to both start running and appearing when called. However, if I understand the code correctly, the vis are all running at the same time and only the chosen one is displayed. I changed the original example so that it aborts before the next one is loaded. I have simplified it into its own vi and attached it to give you a better understanding.

-Using asynchronous calling is good for when you do not need the results of the subvi immediately. However, some of the data from a vi will be needed for the subsequent vi running on the subpanel. Would I use an asynchronous call and collect option? Or global/shared variables? Or queues?

 


You're correct in your interpretation, you'll start all 5 at once and then show and kill one at a time. Depending on what needs to happen and react in your main VI, it might work with simply dropping the called VI's as subVIs. Since you're using VI server i'll assume you'll need to have your main VI responsive and the other VI's need the dynamic call.

I like the proposed idea of HostToClient and ClientToHost queues. For now it probably is sufficient with a String data type to start of simple. Make a VI of each 'Obtain HTC queue' and 'Obtain CTH queue' so you can use it in all VI's easily.

With that solution you don't actually need any inputs on the subVI's, you'll Obtain the queues internally.

Now it's very easy to Control your subpanel'd VI, enqueue 'stop' to HTC in your main VI and dequeue and react to it in the sub-vi.

Look at Producer/consumer queue-example.

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
Message 7 of 7
(2,564 Views)