Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Avoiding repeat operations

Say for example I had the following UI with an actor registered for Connect.Value changed and Search.Value change.

UI.png

Upon receiving the Connect event I would like to attempt connection to the device which will take >5 seconds.

Because of the asynchronous nature of the Actor framework, sending an actor message from the event handler that  runs the connection routine would mean that the user can repeatedly click the connect button and add more connect messages to the queue even before the first connect operation has completed. A similar situation applies to the search operation. What is the best way of avoiding this?

At the moment I’m thinking of having one actor for the controller that monitors/sets an ‘operation running’ flag. If the flag is not true, it sets it to true and sends the connect message to another loop/actor which does the actual connecting. If it is already true, an ‘Operation already running’ dialog is displayed.

Upon connecting or failing a message is sent back to the controller to tell it about the outcome. This then sets the ‘operation running’ flag back to false and the user can click the connect button again.

Is there an easier way than this? Am I over complicating things (probably)?

I have lots of scenarios like this within my program and this means creating lots of messages/actors/parallel loops overall.

Thanks.



Using LV2018 32 bit

Highly recommended open source screen capture software (useful for bug reports).

https://getsharex.com/
0 Kudos
Message 1 of 8
(6,039 Views)

You could also send a replyable message to your actor that does the bluetooth connection. I'm not sure if its a direct child or if you channel the message up and back down an inheritance chain, but you probably already have those message connections in place between the UI and the controller.  At your UI, simply lock the connect out until you get a response.  This limits you to one connect at a time of course, but seems that is what you want.  The UI can have its own state information to store that it is waiting for response and register for a user event to handle the callback when the connection has been finished or failed after 5 seconds.  Then, the UI can reenable the connect button and clear that state information that it is waiting on.

Message 2 of 8
(4,648 Views)

matt.baker wrote:

this means creating lots of messages/actors/parallel loops overall.

Why do you need to create any more actors/loops than the two you start with (the UI, and whatever the UI is a UI for)?  And the only extra message you seem to need is "Reenable UI".

BTW, I usually use the "Cursor Busy" VI to disable the UI. though you could instead display a modal VI while your connect operation is ongoing.

Message 3 of 8
(4,648 Views)

Thanks both for your suggestions.

One other question: How would would you go about canceling an operation part way through? I normally do this with a boolean reference that I periodically checked when using non actor code.

If I send a cancel message, this obviously wouldn't work as the actor core is busy carrying out the operation. Would you pass some sort of "cancel" reference to the UI which it can set?

It would be so much easier if LabVIEW natively passed the object data by reference like C/lots of other languages 😕 I could then just run a method in the UI that sets a cancel flag.



Using LV2018 32 bit

Highly recommended open source screen capture software (useful for bug reports).

https://getsharex.com/
0 Kudos
Message 4 of 8
(4,648 Views)

You can certainly gain the same capability by including a reference to a cancel flag in your object data.

Message 5 of 8
(4,648 Views)

matt.baker wrote:

One other question: How would would you go about canceling an operation part way through? I normally do this with a boolean reference that I periodically checked when using non actor code.

If I send a cancel message, this obviously wouldn't work as the actor core is busy carrying out the operation. Would you pass some sort of "cancel" reference to the UI which it can set?

It would be so much easier if LabVIEW natively passed the object data by reference like C/lots of other languages 😕 I could then just run a method in the UI that sets a cancel flag.

Long-running actions shouldn't be in your actor message-receiving loop; they should be handled by a helper loop.  If the actor receives a "Cancel" message, it can cancel the operation by using a reference shared between message-loop and helper loop (I usually use a Notifier, rather than a control reference). 

0 Kudos
Message 6 of 8
(4,648 Views)

Ah, I see. Thanks for the info.

I think I have been abusing the Actor Framework so far on some of my tasks 😛

I'm at the stage of understanding how the framework operates, now trying to learn the best implementation patterns people have come up with. No doubt I'll be back again with more questions in the near future.

Also, just had a read of https://decibel.ni.com/content/message/65246 - Interesting.



Using LV2018 32 bit

Highly recommended open source screen capture software (useful for bug reports).

https://getsharex.com/
0 Kudos
Message 7 of 8
(4,648 Views)

The usual way to prevent more button clicks is to just set the Disabled property on the button in the Value Changed frame of the event structure and only re-enable it once the UI gets a message back that the first click is done processing.

Message 8 of 8
(4,648 Views)