2010-08-05 110 views
8

我創建了一個帶兩個按鈕的簡單窗口,第一個調用持續很長時間的函數, 第二個將變量的值設置爲「stop」 TRUE, 最初設置爲FALSE。如何使用「停止按鈕」來停止進程

我的意圖是,通過按下第一個按鈕,它運行一個漫長的過程, 如果停止變量設置爲TRUE或FALSE,每循環控制, 如果該值爲TRUE函數應該返回,所以進程停止。

... 

static BOOL stop = FALSE; // My variable defined somewhere 

... 

int longProcess() // My function 
{ 
    while(stop == FALSE) { 
     // do something 
    } 
    return 0; 
} 

... 

switch (msg) 
{ 
    case WM_CREATE: 
    { 
          ... 

     Button1 = CreateWindowEx(0, 
             TEXT("BUTTON"), 
             TEXT("Start"), 
             WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 
             100, 100, 100, 20, 
             hWnd, 
          (HMENU)BUTTON_START, 
          NULL, 
             NULL); 

     Button2 = CreateWindowEx(0, 
          TEXT("BUTTON"), 
         TEXT("Stop"), 
         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 
         200, 200, 100, 20, 
           hWnd, 
           (HMENU)BUTTON_STOP, 
           NULL, 
           NULL); 
          ... 

    } 
    break; 

    case WM_COMMAND: 
    { 
     switch (LOWORD(wParam)) 
     { 

         case BUTTON_START: 
          longProcess(); // Starts the process 
       break; 

         case BUTTON_STOP: 
          stop = TRUE; // Should stop the process 
       break; 

     } 
    } 
    break; 

    ... 

} 

}

的問題是,當我按下第一個按鈕的過程中正常啓動, 但是當我按下以停止該過程沒有第二個按鈕發生, 我注意到,停止變量僅在過程結束後設置爲TRUE。 我以爲可能在有關消息隊列的問題...

什麼可能是最好的解決方案? 在那裏和那樣調用longProcess()是正確的? (我是新手:))

謝謝!

+0

歡迎來到併發編程的世界! – 2010-08-05 14:09:18

回答

13

您需要在單獨的線程上運行長進程,並且您的方法應該可行。

這是,而不是隻調用longProcess函數開始按鈕點擊,創建一個線程,並運行它的長處理。

發生什麼事是您的長時間進程阻塞了您的UI線程,該線程負責處理UI事件。所以,停止按鈕點擊將不會被處理,直到longProcess()完成。

5

在Delphi中,我們有Application.ProcessMessages(),它基本上處理所有未決的消息並返回。並且您可以將此線路循環,以使UI 更具響應能力

有了這樣的功能,你可以做到這一點

while(stop == FALSE) { 
    // do something 
    ... 

    ProcessPendingMessages(); 
} 

編輯: 這適用,如果你不想分裂代碼單獨的線程 - quick'n'dirty解決方法

+2

在windows中,它是'GetMessage' /'DispatchMessage' – sje397 2010-08-05 12:57:08

3

如何使用PeekMessage

int longProcess() // My function 
{ 
    while(stop == FALSE) 
    { 
     // do something 

     while (PeekMessage(&msg, hwnd, 0, 0, PM_NOREMOVE)) 
     { 
      // check for the stop button 
      if ((msg.message == WM_COMMAND) && (LOWORD(wParam) == BUTTON_STOP)) 
       stop = TRUE; 
      } 
     } 
    } 
} 
3

在最低限度,你就必須與揮發性關鍵字來聲明你的變量。但最好的辦法是使用一個事件。 CreateEvent()初始化它,SetEvent()發出停止條件,WaitForSingleObject()用0超時來測試它。

1

作爲AOI Karasu的答案的變體,MFC有CWinThread :: PumpMessage()。

我在工作線程循環中使用它來保持它們的響應。它效果很好。