Hi,
Mais um pequeno artigo abordando a linguagem C ;)
A sintaxe da função SuspendThread é:
DWORD WINAPI SuspendThread(HANDLE thread_handle);
thread_handle:
handle da thread que se deseja pausar;
A função retorna o valor ZERO se a thread especificada for interrompida corretamente, ou retorna -1, se o processo falhar.
A função ResumeThread possui praticamente a mesma sintaxe:
DWORD WINAPI ResumeThread(HANDLE thread_handle);
thread_handle:
handle da thread que se deseja pausar;
A função também retorna o valor ZERO se a thread for resumida corretamente, ou retorna -1, se falhar.
Até agora, os exemplos mostraram como utilizar uma Thread. Veremos como proceder com duas ou mais Threads.
Exemplo:
#include <windows.h>
DWORD WINAPI Thread1(LPVOID);
DWORD WINAPI Thread2(LPVOID);
DWORD WINAPI Thread3(LPVOID);
int main()
{
DWORD id[3];
HANDLE th[3];
th[0] = CreateThread(0,0,Thread1,0,0,&id[0]);
th[1] = CreateThread(0,0,Thread2,0,0,&id[1]);
th[2] = CreateThread(0,0,Thread3,0,0,&id[2]);
if(th[0] == 0 || th[1] == 0 || th[2] == 0)
{
MessageBox(0,"Ocorreu um erro ao criar as Threads","Erro",0x10);
return 1;
}
MessageBox(0,"Mensagem da função MAIN","LOL",0x40);
WaitForMultipleObjects(3,th,1,INFINITE);
int i;
for(i = 0;i<3;i++)
{
TerminateThread(th[i],0);
CloseHandle(th[i]);
}
return 0;
}
DWORD WINAPI Thread1(LPVOID p)
{
MessageBox(0,"Mensagem da Thread 1","LOL",0x40);
return 0;
}
DWORD WINAPI Thread2(LPVOID p)
{
MessageBox(0,"Mensagem da Thread 2","LOL",0x40);
return 0;
}
DWORD WINAPI Thread3(LPVOID p)
{
MessageBox(0,"Mensagem da Thread 3","LOL",0x40);
return 0;
}
Temos um exemplo de um programa que cria 3 threads =).
Vamos analisar:
DWORD WINAPI Thread1(LPVOID);
DWORD WINAPI Thread2(LPVOID);
DWORD WINAPI Thread3(LPVOID);
Definimos cada função de cada Thread: Thread1,Thread2,Thread3.
DWORD id[3];
HANDLE th[3];
Como vamos criar 3 threads utilizaremos arrays para armazenar, os handlers e ID's de cada thread. Note que cada array possui 3 elementos e que têm os índices: 0, 1 e 2.
th[0] = CreateThread(0,0,Thread1,0,0,&id[0]); // Cria a primeira thread
th[1] = CreateThread(0,0,Thread2,0,0,&id[1]); // Cria a segunda thread
th[2] = CreateThread(0,0,Thread3,0,0,&id[2]); // Cria a teceira thread
Portanto:
th[0] = handle da primeira thread;
id[0] = ID da primeira thread;
th[1] = handle da segunda thread;
id[1] = ID da segunda thread;
th[2] = handle da terceira thread;
id[2] = ID da terceira thread;
Note que como temos um array contendo três elementos, fazemos a verificação das threads da seguinte maneira:
if(th[0] == 0 || th[1] == 0 || th[2] == 0) // Se alguma thread não tiver sido criada
{
MessageBox(0,"Ocorreu um erro ao criar as Threads","Erro",0x10); // Erro
return 1; // Encerra
}
Vamos dar atenção ao seguinte trecho que termina as threads e fecha seus handlers:
WaitForMultipleObjects(3,th,INFINITE);
int i;
for(i = 0;i<3;i++)
{
TerminateThread(th[i],0);
CloseHandle(th[i]);
}
Quando estávamos manipulando apenas uma Thread, utilizamos a função WaitForSingleObject(), mas como estamos trabalhando com 3 ao invés de uma, utilizamos a função WaitForMultipleObjects() para aguardar o término da função de cada Thread.
Sintaxe:
QuoteBOOL WINAPI WaitForMultipleObjects(DWORD num_threads, HANDLE * thread_handle,BOOL esperar_todos, DWORD codigo_saida);
num_threads:
número de threads;
thread_handle:
array que contém os handlers das threads;
esperar_todos:
Pode ser TRUE (1) ou FALSE (0). Se 1, o programa aguarda até todos os objetos, no caso as Threads sejam finalizadas; Se 0, o programa aguarda até que alguma das threads finalize.
tempo:
tempo em milisegundos que o programa deve aguardar. Caso a constante "INFINITE" seja especificada, o programa aguarda o tempo necessário até que a Thread seja finalizada, retornando um valor.
Nós declaramos uma variável auxiliar "i" e fazemos um laço for que vai de 0 a 2 - índices do array "th":
int i;
for(i = 0;i<3;i++)
{
TerminateThread(th[i],0); // Termina a thread identificado por th[i]
CloseHandle(th[i]); // Fecha o handle desta mesma thread
}
Não há segredo nas funções de cada thread, veja:
DWORD WINAPI Thread1(LPVOID p)
{
MessageBox(0,"Mensagem da Thread 1","LOL",0x40);
return 0;
}
DWORD WINAPI Thread2(LPVOID p)
{
MessageBox(0,"Mensagem da Thread 2","LOL",0x40);
return 0;
}
DWORD WINAPI Thread3(LPVOID p)
{
MessageBox(0,"Mensagem da Thread 3","LOL",0x40);
return 0;
}
Cada Thread mostra uma mensagem relativa a ela própria.
É importante notar que, nem sempre, as mensagens irão aparecer na ordem:
QuoteMensagem da Thread 1
Mensagem da Thread 2
Mensagem da Thread 3
Isso vai depender do escalonamento de tempo do processador, que seria uma escala na qual os processos são executadas.
Geralmente, uma thread é criada com prioridade normal.
Utilizando a função SetThreadPriority() podemos alterar a prioridade de execução de uma Thread.
Um exemplo:
#include <windows.h>
#include <stdio.h> // printf()
#include <stdlib.h> // system()
DWORD WINAPI Thread1(LPVOID);
int main()
{
DWORD id;
HANDLE th;
th = CreateThread(0,0,Thread1,0,0,&id);
if(th == 0)
{
MessageBox(0,"Ocorreu um erro ao criar as Threads","Erro",0x10);
return 1;
}
SetThreadPriority(th,THREAD_PRIORITY_LOWEST);
printf("Pressione qualquer tecla para sair...");
system("pause > nul");
TerminateThread(th,0);
CloseHandle(th);
return 0;
}
DWORD WINAPI Thread1(LPVOID p){
while(1)
{
Sleep(1000);
MessageBox(0,"Mensagem da Thread 1","LOL",0x40);
}
return 0;}
Um exemplo já visto anteriormente adaptado. O programa cria uma thread que mostra uma mensagem a cada 1 segundo. Ao pressionar uma tecla, a thread é finalizada e o programa encerrado. O único detalhe é a função SetThreadPriority():
SetThreadPriority(th,THREAD_PRIORITY_LOWEST);
Muda a prioridade da Thread para BAIXA. No conjunto de prioridades, temos:
QuoteTHREAD_PRIORITY_LOWEST -> baixa
THREAD_PRIORITY_BELOW_NORMAL -> abaixo do normal
THREAD_PRIORITY_NORMAL -> normal
THREAD_PRIORITY_ABOVE_NORMAL -> acima do normal
THREAD_PRIORITY_HIGHEST -> alta
THREAD_PRIORITY_TIME_CRITICAL -> tempo real
Deve-se tomar muito cuidado ao alterar a prioridade de threads, principalmente se esta for alta. Pode ocorrer, por exemplo, ao cosumo de todos os recursos de processamento do computador, tornando-o mais lento ou até mesmo levar ao seu travamento.
Quanto às Threads, devemos tomar muito cuidado também ao manipulá-las; como por exemplo evitar que duas ou mais Threads acessem uma mesma região da memória, "disputem" tarefas entre si, dentre outros.
Os exemplos apresentados ilustram o funcionamento de threads locais, isto é, criadas e utilizadas dentro do próprio aplicativo. Muitas técnicas como a DLL Injection - que consiste em injetar uma DLL determinada em um processo específico - criam Threads Remotas, isto é, threads que são criadas e executadas em um outro processo. Geralmente, utilize-se a função VirtualAllocEx() para alocar um espaço virtual neste processo e escrever dados no endereço retornado, sucedida da função CreateRemoteThread() - a responsável por criar Threads Remotas.
No entanto, não abordarei a função neste artigo =)
Bem, é isso...
Bye.
he he, parabens denovo, ando sempre lendo seus topicos