Could you explain why it keeps running without the timeout in this setup? Here, after the last element is dequeued, the Dequeue function keeps operating without the timeout.
You didn't send the sentinel value (empty array) so it never stops. Try this:
Small side note about my (unconventional) timeout on the Dequeue. Bert's right to caution about the use of the timeout. In real life I have a lot of code that uses the default infinite timeout for my Dequeues. But I also typically use a QMH-style message / payload pair which lets me use an explicit shutdown message and not *need* a timeout. Here's why I added it in my "v2" code.
In that example code, where a specific sentinel value acts as the secret code to indicate shutdown, it was conceivable (in theory, but very unlikely and maybe nearly impossible in practice) for the upper producer loop to end but then have the attempt to Enqueue the sentinel empty waveform fail. I purposely *didn't* wire the error in for the sentinel Enqueue for this exact reason - to make sure the attempt to Enqueue would run unconditionally. Because any failure of that Enqueue along with the lower consumer loop having an infinite Dequeue timeout would make the code hang.
So just in case that could possibly happen, I put a long 2 second timeout on the consumer's Dequeue to make sure the code couldn't just hang after you clicked Stop. The timeout's much longer than the nominal 0.1 second enqueuing pace of the producer loop, so should never *really* happen during normal runs. But just in case, it's also much shorter than infinity. 😄
Ah Kevin, I didn't see you'd added that. The original file had a 2 second timeout that was actually the cause of the error, so I assumed it just hadn't been deleted.
Yes you do run a balance between an acceptable timeout and a potential for lockup. If you have a 2 second timeout, you can never acquire more than 2 seconds of data without risking a premature failure.
And you're right as well about not wiring up the error to the sentinel Enqueue.
Finally though, one potentially better option would be to try using Channel Wires, which I believe have a built in "this was the last value" functionality. I personally haven't used them but there are lots of people here that really like them.
Upon reflection, I'd now say that the timeout I added was a case of overthinking the problem. (Or more accurately, both over- *and* under- thinking it.)
My real life code with infinite timeouts depends on an unconditionally-enqueued shutdown message rather than a sentinel. And I have many such instances which have worked reliably for hours and days.
But unconditionally enqueuing a shutdown message is no different *really* than unconditionally enqueuing a sentinel. Either way it can only fail if the queue ref is invalid, in which case the consumer infinite-timeout Dequeue would be exiting with an error anyway.
So to the OP, FWIW, stick with the more conventional approach of the infinite Dequeue timeout. But do also remove the 'error in' wire when enqueuing the empty waveform sentinel to make it unconditional. (Note: functions like "Release Queue", "Clear Task", "Close File" are exceptions to normal error behavior. Unlike most functions such as Enqueue or DAQmx Read which bypass their normal code in the presence of an input error, those "end of the chain" functions tend to perform their normal closeout function despite any input error.)
Good to hear 🙂 Glad you're following.
Also don't forget to check out channel wires:
IIRC, the Stream channel has an optional boolean you can use to say "This is the last write" and the reader can see "That was the last data coming in" and can shut down accordingly. I personally don't use them because I've been using queues for so long and I'm used to them, but lots of people really like the streams.