11-15-2017 09:48 AM
@Blokk wrote:
Bob, your example VI is nice and works as you explained. But IMHO the OP does want two separate consumer loops. He thought (me too) that the "many-to-many" expression means we can have multiple writers (as in your example), but also multiple Readers! In your example you read the Channel at a SINGLE place!
Think about the Enigma Decoders working at Bletchley Park. There are Enigma Messages coming in that need to be processed. You have multiple "Readers", each of whom takes one Message and works on it, putting the decoded Message into another "Decoded Message Channel".
Suppose you have multiple Messages that might involve a slow process, say File Copying, but you can have multiple Files being copied at the same time. Create a Producer that gets the Files that need to be copied, and sends it to 20 Message Handler. Each takes one File off the Message Channel and does the Copy Process (let's say it takes 30 seconds). But if you have 20 Handlers, they can all work "in parallel", so at the end of 30 seconds, you might have all 20 done (or "almost" done), for a speed-up of a factor of 20.
A Messenger Channel is like a Queue (but one that does not allow "Enqueue at Opposite End". You can (and I done this) use multiple DeQueuers of a Queue to similarly "Divide and Conquer in Parallel" slow, non-compute-bound tasks.
Still my Favorite Channel Wire!
Bob Schor
11-15-2017 09:56 AM
Something I forgot to mention in my Example (and which, in truth, tripped me up until I remembered it). The Message is a String Control and I'm using "Value Changed" to trigger an Event. If you just drop a Message Control and test it out, you may be disappointed that it doesn't trigger if you enter, say, "Hello<Return>" -- the display blanks, as though you did enter something, but no Event got triggered.
Explanation is really simple -- it took what you entered, and is waiting for you to put something else on the second line. Simply right-click the Control, change it to Limit to Single Line, and now <Return> will cause the Event to trigger. Silly oversight on my part ...
BS
11-15-2017 09:56 AM - edited 11-15-2017 09:58 AM
Bob, thanks fur the detailed explanation! It is clear that if we have multiple readers, we have no control on that, which msg gets in which consumer loop. This can be useful, but i guess the OP wanted to find a way how to have total control on that where to send each msg. So either sending the msg to all consumers, or only to a selected one...
You cannot do this with Messenger Channel, neither with a Queue as you said.
And i just wish for a single wire Channel type, where i could specify the destination(s), so total control over where my messages end up! 🙂
11-15-2017 10:22 AM - edited 11-15-2017 10:25 AM
I created an Idea here: https://forums.ni.com/t5/LabVIEW-Idea-Exchange/New-Message-Channel-wire-type-with-option-to-specify-...
edit: if you think it would be useful, vote for it give Kudos to the Idea! In contrary, if you think it could create problems, or it would not be that useful, comment why. Thanks! 🙂
11-15-2017 01:56 PM
Thanks Bob and Blokk,
You're thoughtful responses lead to the light bulb clicking on about the current implementation of messenger channel wires...it seems to me that the 'many-to-many' documentation may refer to 'many messages to many readers' instead of 'many writers to many readers'. I kinda proved this by putting a do loop around the write endpoint in my original VI with N=2, thus repeating the message. Now with 2 messages (both the same) in the 'queue', both loops get the same message simultaneously. As long as you want the same message going to both loops, this will suffice, to say, send a stop bit to each loop. Bob's enigma machine analogy provided the fuel for this concept to surface.
Blokk, I really think your destination option idea would work well in directing message traffic to many readers. One question though...so each message would get an ID hack (reader/writer) that would ensure proper reception of each message at the designated reader? So then messages intended for, say, loop 2, would be skipped by loop 1 and would be available for reading by loop 2? Yes, this should do nicely, hope NI acts on your suggestion. And also as you suggest, this functionality can be programmed, but it sure would be nice if...
Thanks very much for your help, guys, I'll see what I can do to give multiple kudos!
11-15-2017 02:04 PM
"I kinda proved this by putting a do loop around the write endpoint in my original VI with N=2, thus repeating the message. Now with 2 messages (both the same) in the 'queue', both loops get the same message simultaneously. "
I would be careful with the above assumption. I could imagine a scenario that even if you double the Write action, aka sending the same msg twice, would end up that only one of the consumer loops will process BOTH msgs! So I would not rely on this at all! Imagine if you have some other Writers, which would "enqueued" msgs at the same time when your first Write node fires the double msg: classic race condition!
11-15-2017 02:08 PM - edited 11-15-2017 02:11 PM
"Blokk, I really think your destination option idea would work well in directing message traffic to many readers. One question though...so each message would get an ID hack (reader/writer) that would ensure proper reception of each message at the designated reader? So then messages intended for, say, loop 2, would be skipped by loop 1 and would be available for reading by loop 2? "
Yes, this is the idea.
Edit: and if you like the idea, give kudos to it, at the Idea page, top left, the star symbol... 😉
11-15-2017 04:20 PM
OK, I'm going to vote (by "not Voting") against Blokk's idea, as it adds complexity where it is not needed, and can be handled in a very straight-forward manner with the existing Messenger Channels.
As I understand it (and forgive me if I missed the point), Blokk wants to designate which Message goes to which Reader. That's simple -- simply build a dispatcher. I illustrate by the following example:
I have a list (Array) of passengers going to various destinations. I put a Sentinel at the end of the array (Streams support Sentinels, Messengers do not, no big deal) so "Limbo" really means "End of List". There are three Trains -- one, on Track 3, going to Anaheim, Azusa, and Cucamonga, a second on Track 101 going to Los Angeles, and a third on Track 405 going to San Diego. The following VI uses one Messenger to build a Queue of Passengers, then a second one to send the Queue to Track 3, Track 101, or Track 405.
This particular demo really makes no specific use of the "Messenger" features of the Channel -- you could do the same thing with a Stream! What it does do is exactly what Blokk wanted -- the Dispatcher sends Passengers to exactly the Train that their final destination requires. The case illustrated here would have the Conductor call --
"Train leaving on Track 3, for Anaheim, Azusa, and Cuc....amonga" (a prize for the reader who "gets this", especially if they can "name that voice").
Messenger Channels never divide or duplicate a Message. As I mentioned earlier, you can send Messages to multiple Readers by branching the wires outside a Structure (you can't have Channel Wires branch inside a Structure), and the Messages will be "parcelled out" to the multiple readers, without duplication. So What You See is What You Get.
Bob Schor
11-15-2017 05:05 PM - edited 11-15-2017 05:05 PM
@lebecker wrote:
it seems to me that the 'many-to-many' documentation may refer to 'many messages to many readers' instead of 'many writers to many readers'.
No, "many-to-many" means "Many Writers to Many Readers" (although, in most cases, it is "Many to one" or "One to Many", depending on the need). Just for fun, I wrote a Many to Many (it's not a "real" application, and is unfinished, but it does show three "Producer" Messenger Channels merging into one, and then being "handled" by three "Consumers").
What we have is three Random Number Generators generating 100 random numbers each, throwing them into a pot, and then having three "sorters" take them out one at a time and do what amounts to an "Insertion Sort" (kind of). The Delete Element on the output side removes the 0 element stuck on when the loop initializes. To get the While loops to quit, I used the Timeout, figuring if the loop was idle for a millisecond, it was done.
Bob Schor
11-15-2017 06:26 PM
I have not dug into channels yet, but you can do the things Blokk wants with User Events.
Basically, messages are sent everywhere and a helper loop picks off messages for a local loop.
See
https://forums.ni.com/t5/Example-Program-Drafts/Message-Bus-Architecture-An-Intro/ta-p/3512280
mcduff