05-03-2022 04:44 AM
Hi,
I have 3 while loops as long as I want to stop on command.
- The first one reads a data on a websocket and adds it in a buffer (enqueue)
- The second dequeue elements
- The third dequeue elements and enqueue after changes
What is the best way to stop these 3 loops with a button OR a command ?
Thanks
Solved! Go to Solution.
05-03-2022 05:34 AM
Pretty way:
Queue up a Stop command to your 3 queues and trigger a True to the Stop loop.
Quick and dirty:
Wire the error wire to Stop loop and ditch all queue in your GUI event.
05-03-2022 06:38 AM
I prefer an explicit command used to stop the loops. An alternative would be to create a notifier specifically for triggering you stop. If you have lots of parallel loops the notifier is useful because you can use a single notification to trigger a stop condition to all of your parallel loops. If you use a command, your master loop will have to enqueue a stop command for each loop. If you use the notifier method I would recommend using a timeout of 0. You do not need to wait on it to check for the stop notification. This would require an extra wire into the parallel loop but this can be useful if you have task loops that are not queued message handlers.
05-03-2022 07:36 AM - edited 05-03-2022 07:36 AM
Thank you for your solution @Yamaeda.
I find the first one the most interesting but it causes problems in the loop that only reads the websocket. I have to read an element to know if I have to stop my loop and I don't like that.
I modified your idea to make a queue shared between my 3 loops and which would contain the state of the loops (each loop having now a running state and a disconnect state). When I want to leave my loops, I just have to tell my queue to switch to disconnect state. This works well for one loop.
In the notifier as demultiplexer example, LabVIEW explains that to guarantee that the state is given to the loop, it is necessary to use queue and not notifiers.
Maybe you can help me to understand that I can't receive my state on my 3 loops.
PS : I don't use a dequeue element but a preview queue element
Thanks.
05-03-2022 07:40 AM
Thanks for your solution @Mark
I opted for a solution approaching what you are explaining to me, but I saw in the LabVIEW Notifiers as demultiplexer example that it was better to use queues to guarantee the routing of my data in my loops.
Maybe you could help me based on the above message.
Thank you.
05-03-2022 07:57 AM
Update!
My dequeue element were in timeout -1 so it was blocking my loop. So there's no way to kill a while loop while keeping dequeue element timeout at -1?
05-03-2022 08:16 AM
Preview queue is a hack and shouldn't be used in the manner you are using it. Use the notifier like I suggested. A queue is a many to one relationship. Thta means, you can have multiple enqueuers but you should only have a single dequeuer. A notifier is one/many to many. It is perfect for the stop condition. You simply need your primary control loop to post trigger the notification and all loops that are registered with the notification will receive the stop notification. A notifier is only a single element deep so only the last value placed in it will be read by the loops that are checking it. However, for a stop condition the data is not important, simply that the notification occurred is enough to trigger the stop.
Using the notifier though you cannot use a -1 for your dequeue timeouts for the command queues. If you did you would never see the because queue would wait forever for a command. This is one good argument for using an explicit stop command. The downside is that your primary loop will have to format and queue the stop command for every queue in your system.
Here is the basic format for the notifier.
05-03-2022 10:10 AM
Curiously, you already have a (disconnected!) channel writer in the top loop. What's the purpose? You definitely could use a channel too.
Are all three lower loops (A) asynchronous, operating on completely different tasks or (B) does a single element transverse all three loops in sequence? (dequeue, process in loop 1, enqueue, dequeue in loop 2, process in loop 2, enqueue, dequeue in loop 3, process in loop 3, etc.). In case (B) you could just use a singe consumer loop and some pipelining architecture
05-03-2022 10:13 AM
A queue is a 'single use' machine. If you dequeue from several loops they'll use up the queued data. Think of it as a converyor belt of things/commands, if one worker take a thing it's not there for the next one.
This can be quite useful if you e.g. have slow processes but are not HW limited.
What you need is a an Event (or as mentioned a Notifier, which is a special case of an event) if you only want to use a single item.
In general, Queues are for Many-to-one, Events are for One-to-many.
05-03-2022 10:17 AM - edited 05-03-2022 10:18 AM
KISS!
You have queues already that you can wire a timeout to. I would get rid of the waits, and have the dequeue elements timeout set the rate on the loops. There is a "Timed out?" output you can wire to a case structure if you need to do some regular update in the loops. You can have a stop command, or wire the error of the dequeue elements to the stop and be aware of where you release the queues. Some people might balk at the idea of having some other error on the dequeue element, but in my book any potential error there (other than from releasing the queue) is a no-go bug and should not leave development.