2010-08-05 5 views
8

J'ai créé une fenêtre simple avec deux boutons, le premier appelle une fonction qui dure longtemps, le second définit la valeur d'une variable "stop" à TRUE, initialement définie sur FALSE.Comment arrêter un processus en utilisant un "bouton d'arrêt"

Mon intention est que, en appuyant sur le premier bouton, il court un long processus, qui contrôle si la variable d'arrêt est réglé sur TRUE ou FALSE pour chaque boucle, si la valeur est la fonction doit retourner TRUE, de sorte que le le processus est arrêté.

... 

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; 

    ... 

} 

}

Le problème est que lorsque j'appuie sur le premier bouton le processus démarre normalement, mais quand j'appuie sur le deuxième bouton pour arrêter le rien processus se produit, j'ai remarqué que l'arrêt variable est définie sur TRUE uniquement après la fin du processus. Je pensais que probablement dans un problème lié à la file d'attente de messages ...

Quelle pourrait être la meilleure solution ??? Il est correct d'appeler longProcess() là et de cette façon? (Je suis un débutant :))

Merci!

+0

Bienvenue dans le monde de la programmation concurrente! –

Répondre

13

Vous devez exécuter le processus long sur un thread séparé et votre approche devrait fonctionner.

Ceci est, au lieu de simplement appeler longProcess fonction sur Start Button Cliquez sur, créez un thread et exécutez le processus long dessus.

Ce qui se passe, c'est que votre long processus bloque votre thread d'interface utilisateur, qui est responsable de la gestion des événements de l'interface utilisateur. Donc, Bouton d'arrêt Cliquez sur ne sera pas géré jusqu'à ce que longProcess() se termine.

5

En Delphi, nous avons Application.ProcessMessages() qui traite essentiellement tous les messages et retours en attente. Et vous pouvez mettre cette ligne à cycle pour rendre l'interface utilisateur plus sensible.

Avec la fonction comme vous pouvez le faire

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

    ProcessPendingMessages(); 
} 

EDIT: Cela vaut si vous ne voulez pas diviser code pour séparer fil - quick'n'dirty solution

+2

Dans Windows, c'est 'GetMessage' /' DispatchMessage' – sje397

3

Comment l'utilisation 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

Au minimum, vous devrez déclarer votre variable avec le mot-clé volatile . Mais la meilleure façon de le faire est d'utiliser un événement. CreateEvent() pour l'initialiser, SetEvent() pour signaler la condition d'arrêt, WaitForSingleObject() avec un timeout 0 pour le tester.

1

En tant que variante de la réponse de AOI Karasu, MFC a CWinThread :: PumpMessage(). Je l'utilise dans les boucles de threads de travail pour les garder réactifs. Cela fonctionne très bien.

Questions connexes