Partilhar via


Multithreading: Terminando threads no MFC

Duas situações normais fazem com que um thread seja encerrado: a função de controle é encerrada ou o thread não pode ser executado até a conclusão. Se um processador de texto usasse um thread para impressão em segundo plano, a função de controle terminaria normalmente se a impressão fosse concluída com êxito. No entanto, se o utilizador pretender cancelar a impressão, o thread de impressão em segundo plano tem de ser terminado prematuramente. Este tópico explica como implementar cada situação e como obter o código de saída de um thread depois que ele termina.

Terminação normal de encadeamentos

Para um thread de trabalho, a terminação normal do thread é simples: saia da função de controle e retorne um valor que signifique o motivo da rescisão. Você pode usar a função AfxEndThread ou uma return instrução. Normalmente, 0 significa conclusão bem-sucedida, mas isso depende de você.

Para um thread de interface do usuário, o processo é igualmente simples: de dentro do thread da interface do usuário, chame PostQuitMessage no SDK do Windows. O único parâmetro que PostQuitMessage usa é o código de saída do thread. Quanto aos threads de trabalho, 0 em geral significa conclusão bem-sucedida.

Terminação prematura de threads

Encerrar um thread prematuramente é quase tão simples: Chame AfxEndThread de dentro do thread. Passe o código de saída desejado como o único parâmetro. Isso interrompe a execução do thread, deslocaliza a pilha do thread, desanexa todas as DLLs anexadas ao thread e exclui o objeto thread da memória.

AfxEndThread deve ser invocado de dentro da tarefa a ser encerrada. Se você quiser encerrar um thread de outro thread, você deve configurar um método de comunicação entre os dois threads.

Recuperando o código de saída de um thread

Para obter o código de saída de um dos threads de trabalho ou do thread da interface de utilizador, chame a função GetExitCodeThread. Para obter informações sobre essa função, consulte o SDK do Windows. Esta função leva o identificador para o thread (armazenado no m_hThread membro de dados de CWinThread objetos) e o endereço de um DWORD.

Se o thread ainda estiver ativo, GetExitCodeThread coloca STILL_ATIVE no endereço DWORD fornecido, caso contrário, o código de saída é colocado neste endereço.

Recuperar o código de saída de objetos CWinThread leva uma etapa extra. Por padrão, quando um CWinThread thread termina, o objeto thread é excluído. Isso significa que você não pode acessar o m_hThread membro de dados porque o CWinThread objeto não existe mais. Para evitar essa situação, siga um destes procedimentos:

  • Defina o membro de dados m_bAutoDelete como FALSE. Isso permite que o CWinThread objeto sobreviva após o thread ter sido encerrado. Depois, poderá aceder ao membro de dados m_hThread após o thread ter sido encerrado. Se você usar essa técnica, no entanto, você é responsável por destruir o CWinThread objeto porque a estrutura não irá excluí-lo automaticamente para você. Este é o método preferido.

  • Armazene a alça do thread separadamente. Depois que o thread for criado, copie seu m_hThread membro de dados (usando ::DuplicateHandle) para outra variável e acesse-o por meio dessa variável. Desta forma, o objeto é excluído automaticamente quando ocorre a rescisão e você ainda pode descobrir por que o thread terminou. Tenha cuidado para que o thread não termine antes de poder duplicar o identificador. A maneira mais segura de fazer isso é passar CREATE_SUSPENDED para AfxBeginThread, armazenar o identificador e, em seguida, retomar o thread chamando ResumeThread.

Qualquer um dos métodos permite determinar por que um CWinThread objeto foi encerrado.

Ver também

Multithreading com C++ e MFC
_endthread, _endthreadex
_beginthread, _beginthreadex
ExitThread