Partilhar via


Multithreading: Criando threads de trabalho no MFC

Um thread de trabalho é comumente usado para lidar com tarefas em segundo plano que o usuário não deve ter que esperar para continuar usando seu aplicativo. Tarefas como recálculo e impressão em segundo plano são bons exemplos de linhas de execução. Este tópico detalha as etapas necessárias para criar um thread de trabalho. Os tópicos incluem:

Criar uma linha de execução é uma tarefa relativamente simples. Apenas duas etapas são necessárias para executar o thread: implementar a função de controle e iniciar o thread. Não é necessário derivar uma classe de CWinThread. Você pode derivar uma classe se precisar de uma versão especial de CWinThread, mas isso não é necessário para a maioria dos threads de trabalho simples. Você pode usar CWinThread sem modificações.

Iniciando o tópico

Existem duas versões sobrecarregadas de AfxBeginThread: uma que só pode criar threads de trabalhador e outra que pode criar threads de interface de utilizador e threads de trabalhador. Para iniciar a execução do thread de trabalho usando a primeira sobrecarga, chame AfxBeginThread, fornecendo as seguintes informações:

  • O endereço da função controladora.

  • O parâmetro a ser passado para a função de controle.

  • (Opcional) A prioridade desejada do tópico. O padrão é prioridade normal. Para obter mais informações sobre os níveis de prioridade disponíveis, consulte SetThreadPriority no SDK do Windows.

  • (Opcional) O tamanho de pilha desejado para o thread. O padrão é uma pilha do mesmo tamanho que a thread de criação.

  • (Opcional) CREATE_SUSPENDED se você quiser que o thread seja criado em um estado suspenso. O padrão é 0 ou inicie o thread normalmente.

  • (Opcional) Os atributos de segurança desejados. O padrão é o mesmo acesso que o thread pai. Para obter mais informações sobre o formato dessas informações de segurança, consulte SECURITY_ATTRIBUTES no SDK do Windows.

AfxBeginThread cria e inicializa um CWinThread objeto para você, inicia-o e retorna seu endereço para que você possa consultá-lo mais tarde. As verificações são feitas durante todo o procedimento para garantir que todos os objetos sejam desalocados corretamente caso alguma parte da criação falhe.

Implementando a função de controle

A função controladora define o thread. Quando essa função é inserida, o thread é iniciado e, quando ele sai, o thread termina. Esta função deve ter o seguinte protótipo:

UINT MyControllingFunction( LPVOID pParam );

O parâmetro é um valor único. O valor que a função recebe neste parâmetro é o valor que foi passado para o construtor quando o objeto thread foi criado. A função de controle pode interpretar esse valor da maneira que escolher. Ele pode ser tratado como um valor escalar ou um ponteiro para uma estrutura que contém vários parâmetros, ou pode ser ignorado. Se o parâmetro se refere a uma estrutura, a estrutura pode ser usada não apenas para passar dados do chamador para o thread, mas também para passar dados de volta do thread para o chamador. Se você usar essa estrutura para passar dados de volta para o chamador, o thread precisará notificar o chamador quando os resultados estiverem prontos. Para obter informações sobre como se comunicar do thread de trabalho para o chamador, consulte Multithreading: Dicas de programação.

Quando a função termina, ela deve retornar um valor UINT indicando o motivo da rescisão. Normalmente, esse código de saída é 0 para indicar sucesso com outros valores indicando diferentes tipos de erros. Isto depende puramente da implementação. Alguns threads podem manter contagens de uso de objetos e retornar o número atual de usos desse objeto. Para ver como os aplicativos podem recuperar esse valor, consulte Multithreading: Terminating Threads.

Há algumas restrições sobre o que você pode fazer em um programa multithreaded escrito com a biblioteca MFC. Para obter descrições dessas restrições e outras dicas sobre o uso de threads, consulte Multithreading: Dicas de programação.

Exemplo de função de controle

O exemplo a seguir mostra como definir uma função de controle e usá-la de outra parte do programa.

UINT MyThreadProc( LPVOID pParam )
{
    CMyObject* pObject = (CMyObject*)pParam;

    if (pObject == NULL ||
        !pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))
    return 1;   // if pObject is not valid

    // do something with 'pObject'

    return 0;   // thread completed successfully
}

// inside a different function in the program
.
.
.
pNewObject = new CMyObject;
AfxBeginThread(MyThreadProc, pNewObject);
.
.
.

Sobre o que quer saber mais?

Ver também

Multithreading com C++ e MFC