Multithreading: Criando segmentos de trabalho
Um segmento de trabalho usado para manipular tarefas de plano de fundo que o usuário não deverá esperar para continuar usando o seu aplicativo. Tarefas como o recálculo e impressão em segundo plano são bons exemplos de segmentos de trabalho. Este tópico detalha as etapas necessárias para criar um segmento de trabalho. Os tópicos incluem:
Iniciando o thread.
Implementando a função de controle
Example
A criação de um segmento de trabalho é uma tarefa relativamente simples. Apenas duas etapas são necessárias para obter seu thread em execução: Implementando a função de controle e iniciar o thread. Não é necessário derivar uma classe de CWinThread. Você pode derivar uma classe, se você precisar de uma versão especial do CWinThread, mas ele não é necessário para a maioria dos segmentos de trabalho simple. Você pode usar CWinThread sem modificação.
Iniciando o Thread.
Existem duas versões sobrecarregadas dos AfxBeginThread: uma para segmentos de interface de usuário e uma para threads de trabalho. Para começar a execução de seu segmento de trabalho, chame AfxBeginThread, fornecendo as seguintes informações:
O endereço da função de controle.
O parâmetro a ser passado para a função de controle.
(Opcional) A prioridade desejada do segmento. O padrão é a prioridade normal. Para obter mais informações sobre os níveis de prioridade disponível, consulte SetThreadPriority na Windows SDK.
(Opcional) O tamanho de pilha desejada para o segmento. O padrão é a mesma pilha de tamanho do segmento de criação.
(Opcional) CREATE_SUSPENDED se você desejar que o segmento a ser criado em um estado suspenso. O padrão é 0 ou iniciar o thread normalmente.
(Opcional) Os atributos de segurança desejado. O padrão é o mesmo acesso que o thread do pai. Para obter mais informações sobre o formato dessas informações de segurança, consulte SECURITY_ATTRIBUTES na Windows SDK.
AfxBeginThreadcria e inicializa um CWinThread o objeto, iniciá-lo e retorna seu endereço para que possa consultá-lo mais tarde. As verificações são feitas durante o procedimento para certificar-se de que todos os objetos são liberados adequadamente caso de falha de qualquer parte da criação.
Implementando a função de controle
A função de controle define o thread. Quando essa função é inserida, o thread se inicia e quando ele é encerrado, o segmento 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 de qualquer maneira, que ele escolhe. Ele pode ser tratado como um valor escalar ou de 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 os dados do chamador para o segmento, mas também para passar dados de volta do segmento para o chamador. Se você usar como uma estrutura para passar dados de volta para o chamador, o segmento precisa notificar o chamador, quando os resultados estão prontos. Para obter informações sobre a comunicação do thread de trabalho para o chamador, consulte Multithreading: Dicas de programação.
Quando a função é encerrado, ele deverá retornar um UINT valor que indica o motivo do término. Normalmente, o código de saída é 0 para indicar sucesso com outros valores indicando os diferentes tipos de erros. Esta é puramente dependente de implementação. Alguns segmentos podem manter as contagens de uso de objetos e retornar o número atual de usos desse objeto. Para ver como os aplicativos possam recuperar esse valor, consulte Multithreading: Terminação de segmentos.
Há algumas restrições ao que você pode fazer em um programa multithread escrito com a biblioteca MFC. Para obter descrições sobre essas restrições e outras dicas sobre o uso de threads, consulte Multithreading: Dicas de programação.
Controlando o exemplo de função
O exemplo a seguir mostra como definir uma função de controle e usá-lo 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);
.
.
.