11-26-2013 02:05 AM - last edited on 12-19-2014 11:16 AM by dcarva
Hi all,
I have a code with two buttons placed on the panel, one is RUN, another is STOP. Initially, STOP is disabled and when I kick RUN, the STOP will be disable. But when STOP is kicked, the RUN will be activated.
#include "testimg.h" #include <windows.h> #include <utility.h> #include "asynctmr.h" #include <ansi_c.h> #include <cvirte.h> #include <userint.h> #include <NIDAQmx.h> #include "toolbox.h" static int panelHandle = 0; static int stoprun = 0; int main (int argc, char *argv[]) { int error = 0; nullChk (InitCVIRTE (0, argv, 0)); errChk (panelHandle = LoadPanel (0, "testimg.uir", PANEL)); SetCtrlAttribute(PANEL, PANEL_STOPBUTTON, ATTR_DIMMED, TRUE); errChk (DisplayPanel (panelHandle)); errChk (RunUserInterface ()); Error: if (panelHandle > 0) DiscardPanel (panelHandle); return 0; } int CVICALLBACK MainPanelResponse(int panel, int event, void *callbackData, int eventData1, int eventData2) { if (event == EVENT_CLOSE) QuitUserInterface (0); return 0; } int CVICALLBACK RunButtonResponse (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { if (event==EVENT_COMMIT) { int N=20; stoprun = 0; SetCtrlAttribute(panel, PANEL_STOPBUTTON, ATTR_DIMMED, FALSE); SetCtrlAttribute(panel, PANEL_RUNBUTTON, ATTR_DIMMED, TRUE); for (int i=0; i<N; i++) { // some heavy task // here I use Sleep instead Sleep(5000); ProcessSystemEvents(); Sleep(2000); if (stoprun>0) break; } SetCtrlAttribute(panel, PANEL_STOPBUTTON, ATTR_DIMMED, TRUE); SetCtrlAttribute(panel, PANEL_RUNBUTTON, ATTR_DIMMED, FALSE); } return 0; } int CVICALLBACK StopButtonResponse (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { if (event==EVENT_COMMIT) { stoprun = 1; } return 0; }
My code is designed so to repeat a operation for N times after the START button is kicked. And if STOP button is kicked before the task is finished running. Stop the current application and return false; I wrote the code but it seems doesn't work. It seems that the application cannot be interrupted before the completete of the task. I don't know what's wrong with my code. If you have any experienence with that, could you please tell me what's wrong with my cdoe? Thanks.
Solved! Go to Solution.
11-26-2013 02:42 AM - edited 11-26-2013 02:43 AM
What you are seeing is the expected behaviour: in your loop inside the run button, you have a 5 seconds wait in which the system is frozen, next another 2 sec with the system frozen again. For simulation puroposes you should modify the code this way:
double tini; tini = Timer ();
requestToStop = 0; while (Timer () - tini < 5.0 || requestToStop) { ProcessSystemEvents (); sleep (50); }
The Stop button then must raise a global variable that stops the loop (requestToStop in my example above).
In actual code, such a long lasting process should not be handled inside a control callback: you should place it elsewhere depending on how you want to structure your code so to leave the UI responsive. Available alternatives are:
- A UI timer callback
- An Asynchronous timer callback (similar to the preceding one but executed in a separate thread)
- A separate thread issued with CmtScheduleThreadPoolFunction
Whichever is the solution, the stop button must be handled inside the code by raising a signal that let the processing stop in a secure manner.