Jump to content


Photo
- - - - -

How to open front panel after N milliseconds unless the operation is done


  • Please log in to reply
42 replies to this topic

#1 Aristos Queue

Aristos Queue

    LV R&D: I write C++/# so you don't have to.

  • Premium Member
  • 2,620 posts
  • Location:Austin, TX
  • Version:LabVIEW 2011
  • Since:2000

Posted 30 September 2011 - 09:40 PM

Someone at work was building a dialog for a load progress bar. If the load process took more than N milliseconds, the panel should display. If the load process finished first, the panel should not open. Here's what I wrote for him. Anyone have any improvements to suggest?

[LATER EDIT] Thanks to mje who posted a fully correct solution with all the comments from this thread. You can find the correct solution here.

Snip.png

#2 mje

mje

    The 500 club

  • Premium Member
  • 813 posts
  • Location:Milford MA USA
  • Version:LabVIEW 2011
  • Since:1997

Posted 01 October 2011 - 01:26 AM

I'd probably throw in a release primitive in there for good practice, but otherwise all good I'd say.

#3 Tim_S

Tim_S

    The 500 club

  • Members
  • PipPipPipPipPip
  • 516 posts
  • Location:Michigan
  • Version:LabVIEW 2011
  • Since:1994

Posted 01 October 2011 - 02:22 PM

Hmm... My first inclination would be to use an occurrence instead, but that doesn't change the functionality.

Tim
Tim

"If this was easy our kids would be doing it." - Coworker

#4 Daklu

Daklu

    Bringing the Fu to you

  • Premium Member
  • 1,752 posts
  • Location:Seattle
  • Version:LabVIEW 2009
  • Since:2006

Posted 01 October 2011 - 05:14 PM

Anyone have any improvements to suggest?

Uhh... straighten out your error wire? (j/k ;) ) Clever. I can't help but think about ways of generalizing it into a sub vi that can execute an arbitrary process.

Hmm... My first inclination would be to use an occurrence instead, but that doesn't change the functionality. Tim

Hasn't NI deprecated occurrences in favor of notifiers?

Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.

Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.

There are two secrets to success:
Secret #1 - Never tell everything you know.


#5 asbo

asbo

    I have no idea what you're talking about... so:

  • V I Engineering, Inc.
  • 1,273 posts
  • Version:LabVIEW 2011
  • Since:2008

Posted 01 October 2011 - 05:22 PM

Hasn't NI deprecated occurrences in favor of notifiers?

I hadn't heard that, and would actually find it surprising. Though I haven't used them very many times, I go to occurrences first when I need really simple signalling. DAQ uses them too, doesn't it?

Also, rather than the fill-in-the-blank approach, I would have the VI accept a VI reference and use a blocking Run call. It would force you to make all of the potentially-slow code a subVI, but that may not really be a bad thing. On second thought, though, if the potentially-slow code needed any local data (or returned anything), it would take a more work to pull that off.

#6 drjdpowell

drjdpowell

    The 500 club

  • Premium Member
  • 543 posts
  • Location:Oxford, UK
  • Version:LabVIEW 2011
  • Since:1999

Posted 01 October 2011 - 06:37 PM

Also, rather than the fill-in-the-blank approach, I would have the VI accept a VI reference and use a blocking Run call. It would force you to make all of the potentially-slow code a subVI, but that may not really be a bad thing. On second thought, though, if the potentially-slow code needed any local data (or returned anything), it would take a more work to pull that off.

One could make two subVI's, "Open FP after delay" that outputs the notifier, and "Close FP" that inputs the notifier (as well as the error out of the rest of the code). Then it would be easy to add to any VI and be quite clear. Internals of the two VIs would need to be more complex, with an async call of a third subVI with the actual wait on notification, and some method of making sure "Open..." is finished before "Close..." actually closes the front panel.

-- James

[I'd try and write it if the graphics card on my work laptop hadn't up and died two days ago! "Seven working days to fix" :angry:]

#7 Daklu

Daklu

    Bringing the Fu to you

  • Premium Member
  • 1,752 posts
  • Location:Seattle
  • Version:LabVIEW 2009
  • Since:2006

Posted 01 October 2011 - 06:45 PM

For kicks and grins I whipped up a quick example of a reusable and semi-generic process progress bar using (of course) LVOOP. I wouldn't consider this adequate for a reuse library since it is UI-centric, but it is something I might use as reusable code within an application. Code is in LV2009.

Example Code BD
SimpleExample_BD.png

ProcessProgressBar.DoProcess BD
ProcessProgressBar.lvclass_DoProcess_BD.png

WaitProcess.ProcessRunner BD
WaitProcess.lvclass_ProcessRunner_BD.png

I hadn't heard that, and would actually find it surprising.

FYI... from LV2009 help, Generate Occurrence Function:

Note National Instruments encourages you to use the Notifier Operations functions in place of occurrences for most operations.

Whether or not that means they deprecated occurrences is subject to interpretation I guess.

Attached Files


Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.

Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.

There are two secrets to success:
Secret #1 - Never tell everything you know.


#8 asbo

asbo

    I have no idea what you're talking about... so:

  • V I Engineering, Inc.
  • 1,273 posts
  • Version:LabVIEW 2011
  • Since:2008

Posted 01 October 2011 - 08:10 PM

FYI... from LV2009 help, Generate Occurrence Function:

Note National Instruments encourages you to use the Notifier Operations functions in place of occurrences for most operations.

Whether or not that means they deprecated occurrences is subject to interpretation I guess.


Thanks for the source. I'd like to hear more about this, not because I love occurrences so much as I'm curious why the recommendation arose. The wiki article does mention some "unexpected" behavior - maybe that's it.

#9 mje

mje

    The 500 club

  • Premium Member
  • 813 posts
  • Location:Milford MA USA
  • Version:LabVIEW 2011
  • Since:1997

Posted 01 October 2011 - 10:38 PM

I'd hazard a guess that notifiers aren't recommended due to their behavior being different than the other sync objects. The behavior is a little odd, but once understood they are perfectly usable.

#10 Aristos Queue

Aristos Queue

    LV R&D: I write C++/# so you don't have to.

  • Premium Member
  • 2,620 posts
  • Location:Austin, TX
  • Version:LabVIEW 2011
  • Since:2000

Posted 03 October 2011 - 04:35 AM

Let me fix that for you...

> I'd hazard a guess that notifiers occurrences aren't recommended due to their behavior being
> different than the other sync objects. The behavior is a little odd, but once understood they are perfectly usable.


With my amendments, yes, you're correct

It is very hard for most folks I've worked with to understand how and why occurrences work. The Notifier wrapper (it uses occurrences under the hood, as does all sleep/wake behavior of LV) generally makes things clearer.

I'd probably throw in a release primitive in there for good practice, but otherwise all good I'd say.

Yeah, that should be added since he's probably calling this as a subVI repeatedly.

#11 mje

mje

    The 500 club

  • Premium Member
  • 813 posts
  • Location:Milford MA USA
  • Version:LabVIEW 2011
  • Since:1997

Posted 03 October 2011 - 11:54 AM

Hah, yes, of course I meant occurrences. Doh.

#12 Tim_S

Tim_S

    The 500 club

  • Members
  • PipPipPipPipPip
  • 516 posts
  • Location:Michigan
  • Version:LabVIEW 2011
  • Since:1994

Posted 03 October 2011 - 05:04 PM

It is very hard for most folks I've worked with to understand how and why occurrences work. The Notifier wrapper (it uses occurrences under the hood, as does all sleep/wake behavior of LV) generally makes things clearer.


The amusing part of that is I'm the opposite... I understand occurrences better than notifiers. Though, in full disclosure, I can't ever recall using notifiers.

Tim
Tim

"If this was easy our kids would be doing it." - Coworker

#13 rolfk

rolfk

    LabVIEW Aficionado

  • Premium Member
  • 2,045 posts
  • Location:Netherlands
  • Version:LabVIEW 2011
  • Since:1992

Posted 07 October 2011 - 03:11 PM

Occurrences are the underlaying functionality of all LabVIEW asynchronous operations. However they have a few limitations in itself.

1) They don't allow for any data to be associated to them
2) They have somewhat confusing semantics
3) You can get a triggered occurrence from set occurrence invocations that happened before the wait occurrence was called even when ignore previous is true. This can be worked around easily by checking for the actual event in some other ways and reentering a wait if the event wasn't really true, but one needs to be aware of it.

#14 Aristos Queue

Aristos Queue

    LV R&D: I write C++/# so you don't have to.

  • Premium Member
  • 2,620 posts
  • Location:Austin, TX
  • Version:LabVIEW 2011
  • Since:2000

Posted 07 October 2011 - 08:38 PM

I had a conversation with our chief architect whose been working on LV since version 0.1 and who created the occurrences long long ago. Here is THE correct way to use occurrences:

First build a system which polls busily for whatever it is the occurrence will signal. You need to be able to determine the state of things without an occurrence. This creates a correct, but inefficient busy waiting implementation. Once that works, add an occurrence to alleviate the inefficient waiting. Do not remove the actual polling. In other words, use the occurrence only to indicate that "it is probably a good time to check on that thing...".

[Later Edit] I added a much better example of the usage of occurrences a few days later in this thread. Read it here.

In other words, start with this:
1.png
and then go to this:
2.png

As I understand it, occurrences don't have thread safety on their state because they are the building blocks by which thread safety for state in higher level APIs is built.

#15 ShaunR

ShaunR

    LabVIEW Archetype

  • Members
  • PipPipPipPipPipPip
  • 2,224 posts
  • Version:LabVIEW 2009
  • Since:1994

Posted 07 October 2011 - 08:59 PM

I had a conversation with our chief architect whose been working on LV since version 0.1 and who created the occurrences long long ago. Here is THE correct way to use occurrences:

First build a system which polls busily for whatever it is the occurrence will signal. You need to be able to determine the state of things without an occurrence. This creates a correct, but inefficient busy waiting implementation. Once that works, add an occurrence to alleviate the inefficient waiting. Do not remove the actual polling. In other words, use the occurrence only to indicate that "it is probably a good time to check on that thing...".

In other words, start with this:
1.png
and then go to this:
2.png

As I understand it, occurrences don't have thread safety on their state because they are the building blocks by which thread safety for state in higher level APIs is built.

That won't work.
A positive attitude may not solve all your problems, but it will annoy enough people to make it worth the effort. (Herm Albright 1876-1944).

Founder and general mischief maker on www.labview-tools.com.
SQlite aficionado and websocket zealot.
If it 'aint in LabVIEW, then you 'aint got a clue!

#16 Daklu

Daklu

    Bringing the Fu to you

  • Premium Member
  • 1,752 posts
  • Location:Seattle
  • Version:LabVIEW 2009
  • Since:2006

Posted 07 October 2011 - 11:14 PM

That won't work.

Care to elaborate? (I've never used occurences and I'm finding it a bit confusing.)

Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.

Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.

There are two secrets to success:
Secret #1 - Never tell everything you know.


#17 Darin

Darin

    Very Active

  • Members
  • PipPipPip
  • 158 posts
  • Version:LabVIEW 2009
  • Since:1992

Posted 08 October 2011 - 12:56 AM

Care to elaborate? (I've never used occurences and I'm finding it a bit confusing.)


Consider when the local variable is read and comparison is made.

#18 ShaunR

ShaunR

    LabVIEW Archetype

  • Members
  • PipPipPipPipPipPip
  • 2,224 posts
  • Version:LabVIEW 2009
  • Since:1994

Posted 08 October 2011 - 01:43 AM

Care to elaborate? (I've never used occurences and I'm finding it a bit confusing.)

Because the local variable will be evaluated well before the first loop reaches the large number and will present a FALSE to the stop terminal. Everything (in the second loop) then waits for the occurance. Once Loop 1 actually fires; loop 2 then proceeds with the FALSE, goes around again and then waits, once more, on the occurance-which never arrives since the first loop has already terminated.

This is why no-one uses them. Its too easy to get race conditions that hang your app because they don't have a time-out.

It will work correctly IF you put the occurance and the local into a sequence structure that guarantees the local is read AFTER the occurance (another reason no-one uses them since they don't have error terminals and forces you to use those pesky sequence structures.)

Edited by ShaunR, 08 October 2011 - 01:45 AM.

A positive attitude may not solve all your problems, but it will annoy enough people to make it worth the effort. (Herm Albright 1876-1944).

Founder and general mischief maker on www.labview-tools.com.
SQlite aficionado and websocket zealot.
If it 'aint in LabVIEW, then you 'aint got a clue!

#19 mje

mje

    The 500 club

  • Premium Member
  • 813 posts
  • Location:Milford MA USA
  • Version:LabVIEW 2011
  • Since:1997

Posted 08 October 2011 - 02:58 AM

Occurrences do have a timeout.

The main reason occurrences behave differently than the other sync objects is because occurrence refnums are static. The refnum is created when the VI that contains the Generate Occurence function is loaded, not when it is executed. That means that a VI which is reused, say in a loop, the Generate primitive will return the same occurrence on each invocation. This is often counter-intuitive to those that don't understand the mechanics of how occurrences are created and can lead to some serious bugs due to previous values being in the occurrence.

The fact that they're created on load is also the reason there is no need for a destroy primitive. Memory leaks don't happen because repeated calls to Generate Occurrence in the same VI always return a reference to the same instance.

The behavior is very useful if the primitive behaviors are understood though. They just work completely different from all the other synchronization primitives.

#20 ShaunR

ShaunR

    LabVIEW Archetype

  • Members
  • PipPipPipPipPipPip
  • 2,224 posts
  • Version:LabVIEW 2009
  • Since:1994

Posted 08 October 2011 - 03:12 AM

Occurrences do have a timeout.

I stand correct4ed (when did they add that then?)

The main reason occurrences behave differently than the other sync objects is because occurrence refnums are static. The refnum is created when the VI that contains the Generate Occurence function is loaded, not when it is executed. That means that a VI which is reused, say in a loop, the Generate primitive will return the same occurrence on each invocation. This is often counter-intuitive to those that don't understand the mechanics of how occurrences are created and can lead to some serious bugs due to previous values being in the occurrence.

IMHO this is how the other primitives should behave (and that includes diagram, project and control refs). I've lost count of the number of times I have had to correct others' code because the refs aren't closed. It is these primitives that are counter and intuitive rather than the occurrence. Oh for the days when Labview meant you didn't have to worry about memory leaks.

The fact that they're created on load is also the reason there is no need for a destroy primitive. Memory leaks don't happen because repeated calls to Generate Occurrence in the same VI always return a reference to the same instance.

The behavior is very useful if the primitive behaviors are understood though. They just work completely different from all the other synchronization primitives.

Seems to me that they work similarly to a notifier (since they have a timeout) without the pit-fall of memory leaks.

Edited by ShaunR, 08 October 2011 - 03:30 AM.

A positive attitude may not solve all your problems, but it will annoy enough people to make it worth the effort. (Herm Albright 1876-1944).

Founder and general mischief maker on www.labview-tools.com.
SQlite aficionado and websocket zealot.
If it 'aint in LabVIEW, then you 'aint got a clue!