Whenever my actor core's front panel resizes, I want to enqueue a message in its self queue to resize a ceratin subpanel. However, I want to cancel previously sent messages and only keep the latest information so that I don't burden the queue. In the past, I would get all objects from the queue and remove the older entries of that message and reenque the elements. How can I do the same thing with the send queue class?
You cannot. This is a key aspect of the safety net of the Actor Framework -- no toying with the queue. While it might be occassionally useful, it plays ever-lovin' havoc with deterministic order of messages for programmatic control and guaranteed delivery of messages.
I can suggest a couple of alternate solutions, but I don't know the exact setup of your actors. The easiest is to modify your Send function so that it fires a Notifer with the size info and then puts the Notifier refnum into the message. Every send fires the same notifier. If multiple sends happen before the first message gets handled, the notifier keeps getting updated to the latest value. The receiver does a Wait on Notifier with a timeout of zero. If the "timed out" output is true, do nothing because that means you've already handled that resize.
Thanks for the prompt response. That method would filter at the receive side but the additional messages would still get enqueued. Do you have a recommended method to filter at the send side, I was thinking of using an additional queue just for this purpose and checking the queue size before sending, the receiver could read the size using property nodes because it has a reference to the vi so I don't need to send the information along although I could by removing previously enqueued messages and enqueing a new one with the size information.
Let me know what you think, thanks for your time.
I can give you one workaround (in a moment), but the real answer is to handle messages faster on the receiver. Applications are bombarded by events from the operating system, especially mouse move type events, and rapidly dropping them is the name of the game. Generally, you set up some system that can handle the event very fast and tosses the event to some slower system that actually does the real work. For example, handle the event by reading the size and then write the size to a notifier. Have a whole different loop in your Actor Core that waits on the notifier and does the resize. By the time it gets back around to Wait On Notification, the event handler may have dequeued hundreds of events and overwritten the value in the notifier many times. You could also handle one event and record the timestamp and then ignore all further events of that same type that arrive during the next 100 ms (or appropriate window).
You could also have a sender that sends one event but when asked to send another event doesn't do it until it gets a message back from the receiver that says the previous event has been handled.
Those sorts of tricks are pretty standard for event handling systems everywhere.
If you really need to filter on the sender side, I can offer only one workaround: I can imagine is using the Time Delayed Send VI (not actually in the Actor Framework.lvlib but distributed with the AF). You would set the message to be sent in 1 second (or something). If another item on the Send got there before the message got sent, you would send the cancel message and put the new one in for time delay. This is essentially the strategy used for updating LV indicators on the front panel, only we do it with low priority threads instead of with timing. The problem with this approach (or any similar approach) is that it risks the message never arriving because it keeps getting cancelled.
Any sort of playing around with the queue generally has a hole in it somewhere. I have dug into many systems over the years where someone used the Get Queue Status primitive to try to do something clever, and they file the bug to National Instruments that there's a problem with the queues... it has pretty much always been the case that there's a race condition in their code between them checking the queue for some state and then doing something based on that state, but meanwhile the state of the queue has changed. It gets messy. Here There Be Dragons. :-)
I will look into trying to handle the events faster at the receiver side using your suggestions. On an off topic, my project all of the sudden is taking a long time to build and once it does, the executable seems to hang as I close the program. All the functionality is fine until I try to close the main window, at that point, all the windows close but the exe seems to still be running and gives an error about 10 seconds later. I've gone through all my actors and they are all closing but I can't figure out what if anything is still running. I don't see this problem when I run in the developement enviroment. I get the following error dump. Is there an easy way to troubleshoot this?
#Date: Mon, Feb 27, 2012 3:30:36 PM
#OSName: Windows 7 Enterprise Service Pack 1
#AppName: iTools 2011
#Version: 11.0 32-bit
#AppModDate: 02/27/2012 18:53 GMT
#LabVIEW Base Address: 0x30000000
2/27/2012 3:32:02.698 PM
Crash 0x0: Crash caught by NIER
File Unknown(0) : Crash: Crash caught by NIER
minidump id: 5b670972-05ca-452f-9a10-3694f58aa3dc
ExceptionCode: 0xC0000025÷ N
0x3072C874 - lvrt <unknown> + 0
0x3072CEBD - lvrt <unknown> + 0
0x30923EAD - lvrt <unknown> + 0
0x3061F285 - lvrt <unknown> + 0
0x3053D342 - lvrt <unknown> + 0
0x30540CD9 - lvrt <unknown> + 0
0x3056155F - lvrt <unknown> + 0
0x3061EC85 - lvrt <unknown> + 0
0x30620204 - lvrt <unknown> + 0
0x3062016A - lvrt <unknown> + 0
0x30620390 - lvrt <unknown> + 0
0x30620662 - lvrt <unknown> + 0
0x304A20A0 - lvrt <unknown> + 0
0x304A5632 - lvrt <unknown> + 0
0x3049DFFB - lvrt <unknown> + 0
0x3049F092 - lvrt <unknown> + 0
0x3044EE5C - lvrt <unknown> + 0
0x3064FA41 - lvrt <unknown> + 0
0x306500D7 - lvrt <unknown> + 0
0x30642D58 - lvrt <unknown> + 0
0x30642F62 - lvrt <unknown> + 0
0x30646467 - lvrt <unknown> + 0
0x3065D690 - lvrt <unknown> + 0
0x3067D13D - lvrt <unknown> + 0
0x300F0E69 - lvrt <unknown> + 0
0x300F13BA - lvrt <unknown> + 0
0x300F23FB - lvrt <unknown> + 0
0x3083B0A7 - lvrt <unknown> + 0
0x308D1035 - lvrt <unknown> + 0
0x3083B15C - lvrt <unknown> + 0
0x3085DD68 - lvrt <unknown> + 0
0x308D0629 - lvrt <unknown> + 0
0x3085CFB9 - lvrt <unknown> + 0
0x3002875C - lvrt <unknown> + 0
0x30028902 - lvrt <unknown> + 0
0x30028970 - lvrt <unknown> + 0
*** Dumping Bread Crumb Stack ***
*** LabVIEW Base Address: 0x30000000 ***
#** VILinkObjRemoveCore: "C:\Labview Builds\iTools 2011\iTools 2011.exe\1abvi3w\user.lib\_Frameworks\Actor Framework\Actor\Actor.vi"
*** End Dump ***
I *think* we have seen this same problem here in R&D. I've got some people tasked with digging into it. My current thought is that it is somehow related to the "Value (Signaling)" event... are you using that to stop any of your actors?
1) Is your code a project that you could share with me directly? We could analyze it in the lab and have a better idea whether what you're seeing is what we're seeing.
2) You say this came on suddenly... is actor core VI particularly large/complex? What I mean is, is this a VI with just a few subVI calls, maybe even a loop, or is it one of those with a case structure with many cases and tons of code on the diagram?
If it is a large VI, it is possible that you just added a bit of code to cross over a compiler optimization threshold. Can you take a bit of time and go through a do "Create SubVI From Selection" on as a few parts of your diagram to break it down into many smaller VIs and see if the problem goes away?
First, thanks again for your time. I'm sure it's tough finding the time to help with user issues.
I've tried to simplify the code as much as possible but the problem persists. I'm not using value (signaling), I'm creating a user event reference with a boolean control and one of the do.vi of a message handled by the actor core is firing off the event and killing the UI event loop.
The actor core VI itself is not very complex. It's mostly a container with subpanels thats hosts other actors.
I also built a very simple test project just to see if I could troubleshoot the problem and noticed that I couldn't use the "This VI" reference to show and hide the front panel as that was giving an error. I had to create a property node from one of the front panel controls and use the owning vi property to get at the actor core.vi reference. After that change I was able to build an exe that would quit at the end.
I can definetely share my code, what is the best way. Should I email it to you, or should I create another discussion with a more appropriate title and attach the code there?
For anyone else reading this thread: JIV sent me his code and we're investigating the issue. For now, I've suggested that rather than relying on LV's exit procedure to kill his application, instead he should trap the "Application Exit?" event, filter it, and then do a controlled shutdown to bring his VIs to completion, and when everything is stopped, call the LabVIEW Exit primitive as the last step.
Here's a VI snippet.. save the image to your computer then drag-drop it onto a block diagram and it should turn into code.