2009-02-26 4 views
10

je un fil à l'aide fraient AfxBeginThread qui est juste un infini en boucle:Comment tuer un thread MFC?

UINT CMyClass::ThreadProc(LPVOID param) 
{ 
    while (TRUE) 
    { 
     // do stuff 
    } 
    return 1; 
} 

Comment puis-je tuer ce fil dans ma classe destructor?

Je pense que quelque chose comme

UINT CMyClass::ThreadProc(LPVOID param) 
{ 
    while (m_bKillThread) 
    { 
     // do stuff 
    } 
    return 1; 
} 

puis mis m_bKillThread-FALSE dans le destructor. Mais j'ai encore besoin d'attendre dans le destructeur jusqu'à ce que le fil soit mort.

Répondre

19

tuer activement le fil:

Utilisez la valeur de retour de AfxBeginThread (CWinThread*) pour obtenir la poignée de fil (m_hThread) puis passer cette poignée à l'API Win32 TerminateThread. Ce n'est pas un moyen sûr de terminer les threads, alors s'il vous plaît lisez la suite.

En attendant le fil à la fin:

utiliser pour obtenir le membre m_hThread, puis utilisez WaitForSingleObject(p->m_hThread, INFINITE); Si cette fonction retourne WAIT_OBJECT_0, le fil est terminée, la valeur de retour de AfxBeginThread (CWinThread*). Au lieu de INFINITE, vous pouvez également mettre le nombre de millisecondes à attendre avant qu'un délai ne se produise. Dans ce cas, WAIT_TIMEOUT sera retourné.

à votre fil de signalisation qu'il devrait se terminer:

Avant de faire la WaitForSingleObject vient de mettre une sorte de drapeau que le fil doit sortir. Ensuite, dans votre boucle principale du thread, vous vérifiez la valeur booléenne et cassez la boucle infinie. Dans votre destructeur vous définissez ce drapeau puis faites un WaitForSingleObject.

Même de meilleures façons:

Si vous avez besoin encore plus de contrôle, vous pouvez utiliser quelque chose comme boost conditions.

1

Vous devez attendre, jusqu'à ce que le fil fasse tout.

if(WaitForSingleObject(thread_handle, INFINITE) == WAIT_OBJECT_0) 
    ;//all right 
else 
    ;//report error 

Méfiez-vous de la fonction TerminateThread, ce qui est très dangereux.

4

BTW, à propos de TerminateThread(), utilisez-le de cette façon.

DWORD exit_code= NULL; 
if (thread != NULL) 
{ 
    GetExitCodeThread(thread->m_hThread, &exit_code); 
    if(exit_code == STILL_ACTIVE) 
    { 
     ::TerminateThread(thread->m_hThread, 0); 
     CloseHandle(thread->m_hThread); 
    } 
    thread->m_hThread = NULL; 
    thread = NULL; 
} 
1

D'abord, vous devez commencer le fil d'une manière si MFC ne supprime pas l'objet de fil quand il est finished, le paramètre par défaut pour le fil MFC est de se supprimer si vous voulez éteindre ça. Maintenant, dans le thread, vous voulez un mécanisme que le thread appelant peut lui envoyer un signal pour se terminer lui-même. Il y a plusieurs façons, l'une est le WaitForSingleObject pour vérifier l'état du signal ou une autre façon est simplement d'envoyer à ce fil un message pour se terminer. C'est une fin gracieuse plutôt que de le tuer.

Alors que ce thread se termine (= sortie de la fonction de thread, nettoyage), vous pouvez attendre que le thread principal le termine avant de quitter.

 int wait = 2000 // seconds (I am waiting for 2 seconds for worker to finish) 
    int dwRes = WaitForSingleObject(m_thread->m_hThread, wait); 
    switch (dwRes) 
    { 
    case WAIT_OBJECT_0: 
     TRACE(_T("worker thread just finished")); break; 
    case WAIT_TIMEOUT: 
     TRACE(_T("timed out, worker thread is still busy")); break; 
    } 

Notez que le réglage m_bAutoDelete = FALSE ci-dessus rendu possible, nous avons encore une poignée valable lorsque le fil se termine afin que nous puissions attendre sur elle. La dernière chose que vous voulez faire maintenant est de supprimer l'objet CWinThread pour libérer sa mémoire (puisque nous avons pris la responsabilité de le faire).

Questions connexes