Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Time-Delayed Send Message Once

(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:

  • Very basic solution: set a local variable to "True" in the Slider's Value Change event. In the Event Structure's Time-Out case, you check the local variable, and perform the image update.
  • Have a parallel loop run a few times a second to check a Notifier. In the Value Change event, you send a Notification to the Notifier. This causes the image to be updated in the parallel loop.
  • (Anything else?)

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:

  • It enqueues a message for being sent T milliseconds from now.
  • While the message is being enqueued, any attemps to send exactly the same Message to exactly the same Send Queue is ignored.
  • After the T millisecond delay has passed, the Message is sent.

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.

Science & Wires — a blog on LabVIEW and scientific programming
http://scienceandwires.com
0 Kudos
Message 1 of 14
(27,507 Views)

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.

DropStaleEvents.png

0 Kudos
Message 2 of 14
(5,195 Views)

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!

Science & Wires — a blog on LabVIEW and scientific programming
http://scienceandwires.com
0 Kudos
Message 3 of 14
(5,195 Views)

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?

0 Kudos
Message 4 of 14
(5,195 Views)

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.

0 Kudos
Message 5 of 14
(5,195 Views)

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?

0 Kudos
Message 6 of 14
(5,195 Views)

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.

0 Kudos
Message 7 of 14
(5,195 Views)

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?

0 Kudos
Message 8 of 14
(5,195 Views)

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.

0 Kudos
Message 9 of 14
(5,195 Views)

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!

Science & Wires — a blog on LabVIEW and scientific programming
http://scienceandwires.com
0 Kudos
Message 10 of 14
(5,195 Views)