05-03-2011 04:03 PM
Moving the dequeue inside the change index event will help to overcome the wait for new data in the queue.
Have a look at this very simplistic approach to your problem with a lossy queue and timed loop.
JohnCS
05-03-2011 04:25 PM
Hi Mark,
Thank you so much. I am studying the vi right now. Once I am done, I will probably have more questions. This is not a regular producer consumer with event, is it? it seems like both the producer and consumer are using the data.
05-03-2011 04:34 PM
@jyang72211 wrote:
Hi Mark,
Thank you so much. I am studying the vi right now. Once I am done, I will probably have more questions. This is not a regular producer consumer with event, is it? it seems like both the producer and consumer are using the data.
Yes, it does allow for bi-directional between the loops. Essentially anything related to the UI is placed in the loop with the event structure and updates are sent via user events. User interactions can influence the state machine via messages passed through a queue to the consumer loop.
05-03-2011 04:38 PM
Is there a special reason why you used a timed loop? For your second loop, you didn't use dequeue, you are just using preview queue. Were you able to get it to work with dequeue instead of a preview queue?
05-03-2011 05:36 PM
Good questions!
I used the timed loop so I could kill it with the Clear Timing Source.vi when I want to quit. Otherwise you have to wait until the next time the while loop times out. Apps should end as soon as possible after a STOP is called. Also, no local variables!
In the consumer loop, I used Preview so I would not empty the queue. I'll let the Lossy Enqueue take care of keeping the queue current by overwriting the current dataset. That way I can change the index more than once for a given dataset and this allows me to look at more than one index per Producer loop cycle. If Dequeue is used instead, you can only see one dataset and you're back to waiting for the queue to be updated.
You could dequeue the array, check the index and enqueue it again. Lossy enqueue will put a new array into the queue whenever it has one. Some careful placing of a dequeue/enqueue in the producer will allow the consumer to block the producer from adding a new dataset until the previous dataset is dequeued. This is in effect a kind of global variable with antirace prevention.
JohnCS
05-04-2011 11:39 AM
Hi Mark,
I told your advice and made some changes to fit my application. I took out the queue completely, and I am passing data through generate user event. Please let me know if you have any more suggestion. thanks!
05-04-2011 12:49 PM
Without seeing the subVIs I can only comment on the top level VI. I generally like to keep all UI items in the loop with the event structure. That is where I would check the stop button. I I would have an event case specifically for that. I think you may run into problems when you try to exit your VI when using the stop button. The event loop will wait for an event before it can stop. I would use a notifier to stop the upper loop. Put the stop button in the event structure and when the stop button is pressed send a notification. This notifier can be a simple Boolean. In the upper loop check the notification with a 0 timeout value. Be sure to check for the notification AFTER the case has executed. As written your upper loop can execute one more case than you may think.
There is no need for the Wait in the loop with the event structure. You should however have some type of Wait in your other loop. As written it looks like it could free run.
Other than that it looks pretty decent. Again, I can't comment on your subVIs but your top level code is pretty well written.
05-04-2011 09:46 PM
Using clear timing source to stop a timed loop from a parallel loop? I didn't know that you can do this. That's a pretty good idea. I don't really use timed loop. Do you have to create a time source to use it? What is the advantage in creating a time source?
05-05-2011 09:39 AM
Hi Mark,
I have another question. For a two loops program (1st and 2nd loop), I always have the 1st loop to runs a state machine with a test sequence (takes a long time and does not need any user interaction), and I have the 2nd loop to handle the UI (update the UI or get event).
Your example was great, but it is a little different than my application. Your example require communication constantly between the two loops in order to run. However, in my application, the 1st loop always run, and it rarely require the info from the 2nd loop (maybe just a stop boolean).
I am thinking maybe I should create a queue to allow the 1st loop to pass data to the 2nd loop to display and have the 2nd loop to pass a stop boolean when a stop boolean event occur. I know that I can enqueue in both loops, but can I dequeue in both loops too? I feel like I can only do a preview queue in the first loop, so that the 1st loop will not be stuck waiting for the queue element to arrive. Let me know what you think. Thanks!
05-05-2011 10:06 AM - edited 05-05-2011 10:07 AM
I would recommend that you use user events to pass data from your state machine to the UI loop (which should contain an event structure). For stopping the application I would use a notifier that is triggered from the UI loop to the state machine. The state machine would not have to wait on the notification though it could if it were in an idle state. It would have to periodically wake up to run. If your notification is more than simply a Boolean and something more like a notification it can be used to get it out of the idle state. At the appropriate times in the state machine it can check if a notification has arrived. The nice thing about the notification is that it can be used to stop multiple tasks. For example, it can trigger an abort in some long task within your state machine. Using this architecture your state machine loop can be a pure finite state machine.
The reason I prefer the queue is that in most of my cases I do not have a pure finite state machine and I do require other messages to be passed to the state machine. For example I can pass configuration information that is entered on the UI to the state machine anytime there is an update.
Ben has posted a very good article about decoupling your processing tasks from your UI. When you do this you do need some defined API to pass information between the tasks. Queues are a good way of passing that information.