05-15-2006 12:00 PM
05-15-2006 01:15 PM
ProcessSystemEvents() is one way to deal with the problem. The catch being that you can make your program re-entrant if you are not careful. Without knowing what you are doing it is hard to recommend another method. You may be able to maintain another activity using a timer or an async timer as a way to provide that task with "time slices". Or you can spin tasks off into other threads (which an async timer can also help with). If the other task can generate an interrupt or event you may be able to chain that task to a callback. A com port callback would be a good example of this.
The event driven model that CVI uses allows a user to enter long processing loops, but for the reasons you point out, they really are not the way to go. To maintain good user performance you want your callbacks to complete quickly and return control to the main event processing routine. If you can outline your requirements here we can probably provide some more useful suggestions.
05-16-2006 11:17 AM
05-16-2006 12:14 PM
05-17-2006 03:42 AM
Unfortunately, if the code is executing in response to a control callback, a timer event will not be recognised until the original callback completes - it does not interrupt the execution so this approach will not cure the problem.
My approach to this kind of problem would be to have a timer running at, say 0.1 second intervals which triggers a callback to examine which test number we are up to (held in a global) and then execute just one test at a time. This way, you are guaranteed to regain GUI control between each test. If individual tests are uncomfortably long, you will have to find a way of breaking them into sub-tests perhaps, which can be performed independantly. A couple of global test/subtest counters, and some global state variables (to track if testing has finished, in progress, is stopping, or whatever), should allow you to improve the situation significantly without the need to re-structure totally.
JR
05-17-2006 07:57 AM
You could also set the functions to run as a thread. I did this in a program when I wanted to play a music slice (anywhere from 5 seconds to 5 minutes). Initially, my GUI froze while the music played. When I launched the music in a thread, everything was fine. Search for help on CMTScheduleThread for more info.
05-17-2006 07:58 AM
This is difficult to answer, since there are different ways to go, all which have there own merit. Redesigning the program at this point is not really the answer. It was unclear to me if all the test were being executed from a single callback. If they are, breaking this up into decrete test steps that are called by a timer executed routine as was suggested above or another sequencing method will help break program execution into smaller chunks. This is a good practice, but this still will not solve the overall problem within each test step. It is possible to improve performance even though you are executing everything from a single callback. The key is to work on the areas where the program is waiting on an action to take place but is not responding to the user.
I suspect that the serial communication is a likely culprit. If you are spending long periods in wait loops looking for the response from the UUT over the serial port, you will have the user interface locked out. This can be handled by adding ProcessSystemEvents() calls in the serial com wait loops (or actually any wait loops within your tests). The catch is that you must make sure that no other event or callback will execute the same routine that made the last call to ProcessSystemEvents() unless it is made re-entrant. This really is not that difficult since you can "dim" controls that would call into routines that must be excluded, and use flags and post deferred event calls for events that are not generated by the user.
While moving routines like serial port handling to another thread has definite advantages, it is not required that it be done that way. You should be able to get pretty decent user interface response even with the single thread design you have.
05-18-2006 03:01 PM
05-18-2006 04:35 PM - edited 05-18-2006 04:35 PM
I don't think you have to re-write this. If you just need to refresh the screen put ProcessDrawEvents() inside any loops that take a along time to execute or while waiting on a reply over the serial port. If the operator is not doing anything with the test itself, ProcessDrawEvents() in any loop, or at intervals in your test, like between test steps, should help to handle things like the operator draging a window across the screen. Just look for the locations in your code where it spends a long time executing, probably most of the loops spent waiting on some action.
Message Edited by mvr on 05-18-2006 04:40 PM