09-26-2012 09:42 AM
When using asychronous call, is there a way to view and/or kill running clones? Let me explain the structure of my program a bit.
I'm developing a testing suite that can read in test script files and run different (or the same) tests on multiple devices hooked up to a NI chassis with AO modules. The two major components of my program are the CommandParserQueuer (CPQ) and the CommandExecutor (CE). A command queue is created during initialization.The CPQ reads in the script files, translates them into commands, and adds those to the command queue. The commands are bundles of enum states and any data necessary to carry out that action. The CE is a queued state machine. When the queues start getting filled, the CE dequeues elements and performs the actions (e.g. set AO voltage, read data from device, restart device, etc.).
On program quit, a shutdown command is sent to the CE, which just sets the while loop stop to true and allows it to exit. All of this worked fine until I implemented the ability of running multiple tests at once, which meant starting multiple instances of the CE with Start Asychronous Call (options x80 and x40).
Because of my design, I have to run a while loop inside the async calls, which goes against the recommended practice of not doing that. During initalization, I create a command queue and CE for each device plugged in. For example, if I have two devices Device1 and Device 2, two queues are created with those names and two CEs are called with references to those queues. The CEs then sit idle until the queues get filled with elements.
The problem I'm having is that sometimes, but not always, code blocks inside the CEs are throwing errors, and also the CEs do not shutdown as instructed. I have to exit LabView all together. I'd also like to highlight the execution of the clones. Is that possible?
Any thoughts?
Solved! Go to Solution.
09-26-2012 09:49 AM
Labview really needs a task manager but doesn't ahve one. However with that said, you could try and make another queue,notifier or event within the each spawned vi's that sends information back to your launcher such as a reference to that vi or its clone id. From that information you could then selectively shut down your spawned vi's instead of shutting them all down. Also this vi reference would allow you to open the front panel and trace execution.
Its a pain, i'm dealing with the same thign right now. Maybe others on the forum have better ideas.
You could look at the actor framework as well. It will spawn clones for you and give a queue for communicating with directly with them. You still have to make a table to identify queues, but it might help with your program.
09-27-2012 08:02 AM
Going from one instance to multiple instances has a several pitfalls. You seem to have successfully navigated some of them, but not all. As Jed394 mentioned, the actor framework should help with start and shutdown, but it sounds like your error is more due to a shared resource conflict. That resource conflict could be either hardware or software. Some things to look for:
Good luck. Let us know if we can help more.
09-27-2012 08:19 AM
A task manager of sorts is what I was looking for. It's too bad we don't have one. The actor framework looks interesting. It would require a substantial rewrite of my code, but I'll try it out.
I did figure out my problem. It was a resource conflict of sorts. I have LabView import DLLs to communicate with the equipment I'm testing, and those libraries do not like receiving commands for the same device from multiple threads. That shouldn't happen in my LabView program, except in a case where a user clicks a certain button while a test is running. My short term fix was to insert that action in front of that device's command queue. In the long term, I need to rewrite my DLL to also put commands in a queue.
Anyway, thanks for the help guys.
09-27-2012 08:33 AM
A straighforward way out of this problem is to create a queue based processing loop for the resource in question. All requests then go to this loop (this is an "actor") via the queue. The loop can keep track of the state of the device and serializes access to the device to avoid problems. You don't even need a subVI to do this, just add another loop to your block diagram. I would probably implement it as a subVI (free-running, at that), but that is a personal choice.