04-20-2012 04:41 AM
(note: new version of code uploaded on 2012.05.16)
When doing UI programming in LabVIEW, I quite frequently encounter the situation where I want a "Value Change" event to lead to a piece of code being executed with a small delay. For example, a Slider to change the contrast of an image will generate dozens of "Value Change" events when the user is changing the Slider with the mouse, but you only want to update the image a few times a second.
AFAIK, there's a few ways to solve this:
Another solution is attached to this message (LV 2011 code). It is basically an adaptation of the Actor Framework's "Time-Delayed Send Message" VIs, which prevents a message from being sent more than once simultaneously.
It does the following:
Just like in the original "Time-Delayed Send Message", it is possible to pre-empt the message after enqueueing it.
The code uses a Functional Global Variable to keep track of the messages currently enqueued. If there would be other ways to solve this, I'd be very interested. I do have the impression that the performance of this implementation is not particularly smashing — but it might be good enough for most applications.
Any comments would be appreciated; I hope someone finds this code useful.
Best,
Onno
Message was edited by: onnodb
Uploaded new version of the code (2012.05.15); old version had a nasty little race condition in it.
04-20-2012 07:54 AM
onnodb wrote:
- (Anything else?)
I usually have a local variable of the control in the Vaue Change event frame, and only do the update code if it is equal to the New value of the event. This essentially throws away all the stale events and updates as rapidly as possible.
04-20-2012 08:03 AM
drjdpowell wrote:
I usually have a local variable of the control in the Vaue Change event frame, and only do the update code if it is equal to the New value of the event. This essentially throws away all the stale events and updates as rapidly as possible.
Hey, that's a clever trick! Thanks!
04-20-2012 09:32 AM
drjdpowell wrote:
I usually have a local variable of the control in the Vaue Change event frame, and only do the update code if it is equal to the New value of the event. This essentially throws away all the stale events and updates as rapidly as possible.
Maybe it's too early in the morning and my brain hasn't fully turned on yet... I don't see how your code snippet throws away anything. Aren't NewVal and the local variable are always going to be equal to each other in the Value Change event?
If it was the Value Change filter event, then yes, I can see how they would be different. But then they're always going to be different and your True case will never execute.
What am I missing?
04-20-2012 11:34 AM
NewVal was the value after the event; the local variable is the value right now. Sliders (and similar controls like cursors on graphs) can fire several Value Change events per second and can stack up if the update code can't execute fast enough (my above code example runs an SQL query). Only the last event in the queue has NewVal equal to the current actual value accessed by the local. So this code throws away stale events.
04-20-2012 11:46 AM
Right. I understand now.
I assume your update code runs in a separate loop? Wouldn't that make the Update Displayed Subset messages back up in the display loop queue and have the display lag behind the user input?
04-20-2012 12:08 PM
No, same loop. The point is if I finish an update and come back to the event structure when there multiple events stacked up, I quickly discard the stale ones and get to the latest. This keeps the display lag to a minimum.
04-20-2012 12:16 PM
No, same loop.
I see. That trick wouldn't work with my style because the event loop always dispatches messages to other loops that do the actual work, so the event queue doesn't get backed up.
If you're running a SQL query in a UI loop, what happens if your database is slow or unresponsive?
04-20-2012 12:52 PM
drjdpowell: One caution on your trick: the Value Changed will fire even if the same value was written to the indicator. That means that your comparison trick won't filter out the events if you get a long stream of the same value being written to the FPTerminal.
04-20-2012 01:55 PM
Ah, btw, AQ: one quick question about the implementation of "Time-Delayed Send Message": you're opening a reference to the re-entrant Core VI using an options flag of "0xC0". The flag is labeled as "Fire & forget" in the code, but the LabVIEW help doesn't mention this flag. Is there something special about it? Why not use "0x80" (if I recall correctly)?
Just curious; thanks!