wanchin
asked on
Urgent!! How to cancel an operation which is running currently?
I have a dialog that do stereo fusion processing. It takes about 4 minutes to accomplish the fusion task. What if the user wants to stop/cancel the process while it is running, so that the process is terminated? I've created a stop button. How can I do this? Can anyone pls provide me with the appropriate source code? Thank you very much!!
Hi,
The info is less. bcoz how the processing is done?, a continous loop?.
But I can suggest one method. Have a boolean flag. Continue processing if that flag is true. And break the processing if that flag is false. Somewhere in the processing time u have to check that flag regularly. And whenever user presses the stop button, make that flag as false.
There is one more method. Have the flag in the same way. Do Ur processing in a thread. In the thread check for that flag.
Try it out.
VinExpert
The info is less. bcoz how the processing is done?, a continous loop?.
But I can suggest one method. Have a boolean flag. Continue processing if that flag is true. And break the processing if that flag is false. Somewhere in the processing time u have to check that flag regularly. And whenever user presses the stop button, make that flag as false.
There is one more method. Have the flag in the same way. Do Ur processing in a thread. In the thread check for that flag.
Try it out.
VinExpert
Hi wanchin,
To VinExpert: if it's really a continuous loop just a flag want solve the problem, because the dialog doesn't recieve the buttons press message until the loop terminates. I.e:
CMyDlg::Calc()
{
while( ... ) // or for
{
// do lengthy calculation here
}
}
The problem with such a loop is that no messages can be processed while loop is running. For this you have several ways:
- redesign your calculation to be done in idle time, when dialog does not recieve any messages. This could be a lot of work.
- move your calculation to a seperate thread. Even a lot of work with synchronization.
- Within you loop check incoming messages and dispatch them, i.e. like this
CMyDlg::Calc()
{
int count = 0;
MSG msg;
m_bContinueLoop = TRUE;
while( m_bContinueLoop ) // m_bContinueLoop is the flag which is reset in the stop buttons message handler
{
if ( ( ++count % 100 ) == 0 )
{
// every hundreth loop check messages
while ( ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
::DispatchMessage( &msg );
if ( msg.message == WM_CLOSE ) // you should check for WM_QUIT and WM_DESTROY also...
return; // break calculation with WM_CLOSE
}
}
// do lengthy calculation here
}
}
this will allow your dialog to process message as usual.
Now you can simply call i.e. m_bContinueLoop = FALSE; from the stop button's message handler.
hope that helps,
ZOPPO
To VinExpert: if it's really a continuous loop just a flag want solve the problem, because the dialog doesn't recieve the buttons press message until the loop terminates. I.e:
CMyDlg::Calc()
{
while( ... ) // or for
{
// do lengthy calculation here
}
}
The problem with such a loop is that no messages can be processed while loop is running. For this you have several ways:
- redesign your calculation to be done in idle time, when dialog does not recieve any messages. This could be a lot of work.
- move your calculation to a seperate thread. Even a lot of work with synchronization.
- Within you loop check incoming messages and dispatch them, i.e. like this
CMyDlg::Calc()
{
int count = 0;
MSG msg;
m_bContinueLoop = TRUE;
while( m_bContinueLoop ) // m_bContinueLoop is the flag which is reset in the stop buttons message handler
{
if ( ( ++count % 100 ) == 0 )
{
// every hundreth loop check messages
while ( ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
::DispatchMessage( &msg );
if ( msg.message == WM_CLOSE ) // you should check for WM_QUIT and WM_DESTROY also...
return; // break calculation with WM_CLOSE
}
}
// do lengthy calculation here
}
}
this will allow your dialog to process message as usual.
Now you can simply call i.e. m_bContinueLoop = FALSE; from the stop button's message handler.
hope that helps,
ZOPPO
Hi,
Yes, But a thread will be a better solution I feel.
VinExpert
Yes, But a thread will be a better solution I feel.
VinExpert
Well, I think idle time processing would be even good, but both may need lots of work for redesign.
ZOPPO
ZOPPO
ASKER
Zoppo,
I've tried your code but it doesn't work. perhaps i've made some mistakes while inserting the code.
I attach the code of my continuos loop process fuction and a stopbutton function. can you show me exactly where should i make alteration of the code?
void CStereoFusionDlg::OnFusion Button()
{
int X, Y;
int i,j, xL, xR, y;
int dispX, dispY;
int diff, total_diff, min_diff, posXLeft, posYLeft;
int posXLeft2, posYLeft2;
count = 0;
m_stop.EnableWindow(TRUE);
for (y=10; y<=245; y++)
{
for (xR=10; xR<=245; xR++)
{
min_diff = 30000;
for (xL=10; xL<=245; xL++)
{
total_diff = 0;
for (i=-10; i<=10; i++)
{
for (j=-10; j<=10; j++)
{
diff = abs(RightBuf[y+i][xR+j] - LeftBuf[y+i][xL+j]);
total_diff += diff;
}
}
if(total_diff < min_diff)
{
min_diff = total_diff;
posXLeft = xL;
posYLeft = y;
}
}
for (i=-10; i<=10; i++)
for (j=-10; j<=10; j++)
{
diff = abs(RightBuf[y][xR] - LeftBuf[posYLeft+i][posXLe ft+j]);
if(diff < min_diff)
{
min_diff = diff;
posXLeft2 = posXLeft + j;
posYLeft2 = posYLeft + i;
}
}
X = xR;
Y = y;
dispX = xR - posXLeft;
dispX *= dispX;
dispY = y - posYLeft;
dispY *= dispY;
disparity_buf[Y][X] = sqrt(dispX + dispY);
cyclopean_buf[Y][X] = (( RightBuf[y][xR] + LeftBuf[posYLeft2][posXLef t2] ) / 2);
}
m_progress1.SetPos(count);
count++;
}
DisplayDisparityMap();
DisplayCyclopeanView();
}
void CStereoFusionDlg::OnStopBu tton()
{
// TODO: Add your control notification handler code here
}
I've tried your code but it doesn't work. perhaps i've made some mistakes while inserting the code.
I attach the code of my continuos loop process fuction and a stopbutton function. can you show me exactly where should i make alteration of the code?
void CStereoFusionDlg::OnFusion
{
int X, Y;
int i,j, xL, xR, y;
int dispX, dispY;
int diff, total_diff, min_diff, posXLeft, posYLeft;
int posXLeft2, posYLeft2;
count = 0;
m_stop.EnableWindow(TRUE);
for (y=10; y<=245; y++)
{
for (xR=10; xR<=245; xR++)
{
min_diff = 30000;
for (xL=10; xL<=245; xL++)
{
total_diff = 0;
for (i=-10; i<=10; i++)
{
for (j=-10; j<=10; j++)
{
diff = abs(RightBuf[y+i][xR+j] - LeftBuf[y+i][xL+j]);
total_diff += diff;
}
}
if(total_diff < min_diff)
{
min_diff = total_diff;
posXLeft = xL;
posYLeft = y;
}
}
for (i=-10; i<=10; i++)
for (j=-10; j<=10; j++)
{
diff = abs(RightBuf[y][xR] - LeftBuf[posYLeft+i][posXLe
if(diff < min_diff)
{
min_diff = diff;
posXLeft2 = posXLeft + j;
posYLeft2 = posYLeft + i;
}
}
X = xR;
Y = y;
dispX = xR - posXLeft;
dispX *= dispX;
dispY = y - posYLeft;
dispY *= dispY;
disparity_buf[Y][X] = sqrt(dispX + dispY);
cyclopean_buf[Y][X] = (( RightBuf[y][xR] + LeftBuf[posYLeft2][posXLef
}
m_progress1.SetPos(count);
count++;
}
DisplayDisparityMap();
DisplayCyclopeanView();
}
void CStereoFusionDlg::OnStopBu
{
// TODO: Add your control notification handler code here
}
ASKER
Adjusted points from 100 to 150
I have designed a CWaitDialog in one of my project. WaitDialog has a label control and progress bar control and a cancel command button. use can click the cancle button to cancel the processing.
CWaitDialog has methods:
1. SetMessageText(char *szText) for you to display message at every stage of processing.
2. SetPercentComplete(int nIndex) for you to set the progress bar
the sample of the calling code could be as follows:
bool bContinue = true;
CWaitDialog myDlg(&bContinue, "stereo fusion processing"); // give the dialog title and user cancel status variable bContinue.
myDlg.SetMessageText("Begi n Processing ...");
nInc = 0;nIndicator= 0;
for (long i = 0;i< 3000; i++){
if(!bContinue) break; // user cancellation
if (nInc++ == 30){
nInc = 0;
myDlg.SetPercentComplete(n Indicator+ +);
}
}
if you are interested to use this waitdialog, I can give you the source code of this class.
CWaitDialog has methods:
1. SetMessageText(char *szText) for you to display message at every stage of processing.
2. SetPercentComplete(int nIndex) for you to set the progress bar
the sample of the calling code could be as follows:
bool bContinue = true;
CWaitDialog myDlg(&bContinue, "stereo fusion processing"); // give the dialog title and user cancel status variable bContinue.
myDlg.SetMessageText("Begi
nInc = 0;nIndicator= 0;
for (long i = 0;i< 3000; i++){
if(!bContinue) break; // user cancellation
if (nInc++ == 30){
nInc = 0;
myDlg.SetPercentComplete(n
}
}
if you are interested to use this waitdialog, I can give you the source code of this class.
Hi wanchin,
I would put it inside outside the first 'i'-loop (but you can even try if it's enough to put it outside the 'xR'.loop, depends on average reaction time), like this:
// to class add a flag in .h file
class CStereoFusionDlg : ...
{
...
BOOL m_bCancel;
...
}
// in function
MSG msg;
m_bCancel = FALSE;
for (y=10; y<=245; y++)
{
for (xR=10; xR<=245; xR++)
{
min_diff = 30000;
for (xL=10; xL<=245; xL++)
{
total_diff = 0;
for (i=-10; i<=10; i++)
{
for (j=-10; j<=10; j++)
{
diff = abs(RightBuf[y+i][xR+j] - LeftBuf[y+i][xL+j]);
total_diff += diff;
}
}
while ( ::PeekMessage( &msg, m_hWnd, 0, 0, PM_REMOVE ) )
{
::DispatchMessage( &msg );
if ( msg.message == WM_CLOSE ) // check for WM_QUIT, WM_DESTROY
return; // break calculation with WM_CLOSE
}
if ( m_bCancel )
return;
....
}
}
}
void CStereoFusionDlg::OnStopBu tton()
{
m_bCancel = TRUE;
}
hope that helps,
ZOPPO
I would put it inside outside the first 'i'-loop (but you can even try if it's enough to put it outside the 'xR'.loop, depends on average reaction time), like this:
// to class add a flag in .h file
class CStereoFusionDlg : ...
{
...
BOOL m_bCancel;
...
}
// in function
MSG msg;
m_bCancel = FALSE;
for (y=10; y<=245; y++)
{
for (xR=10; xR<=245; xR++)
{
min_diff = 30000;
for (xL=10; xL<=245; xL++)
{
total_diff = 0;
for (i=-10; i<=10; i++)
{
for (j=-10; j<=10; j++)
{
diff = abs(RightBuf[y+i][xR+j] - LeftBuf[y+i][xL+j]);
total_diff += diff;
}
}
while ( ::PeekMessage( &msg, m_hWnd, 0, 0, PM_REMOVE ) )
{
::DispatchMessage( &msg );
if ( msg.message == WM_CLOSE ) // check for WM_QUIT, WM_DESTROY
return; // break calculation with WM_CLOSE
}
if ( m_bCancel )
return;
....
}
}
}
void CStereoFusionDlg::OnStopBu
{
m_bCancel = TRUE;
}
hope that helps,
ZOPPO
ASKER
Thank you very much, Zoppo! It works now. How can i transfer the points to you?
wanchin
wanchin
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
BN_CLICKED for that button.
On that function give the following code
void YourDialog::OnExitButtonCl
{
//only you write the following
//single line of code
PostMessage(WM_QUIT,0,0);
}