Fórum Threads! Threads! Threads! #283373
30/05/2005
0
Estou com o seguinte problema: tenho uma aplicação que executa uma série de passos seguidos, sendo que um dos passos no meio consiste em um gargalo de velocidade (é uma varredura no registro do Windows). Para melhorar o desempenho resolvi usar threads, dividindo cada hive do registro para uma thread. Assim uma thread vai varrer a HKEY_CLASSSES_ROOT, outra a HKEY_LOCAL_MACHINE, e assim sucessivamente, ao mesmo tempo. Só que é sabido que quando se lança uma thread o código é executado como em ´background´ em relação à linha de execução principal:
Step1; Step2; StepRegistry; // lança threads e passa para Step4 Step4;
Sendo que eu não desejo esse efeito assim. Eu quero executar código paralelo mas parar o código da aplicação até que todas as threads terminem. Vejam: no caso acima, StepRegistry lança as threads e [b:de28e92f43]imediatamente[/b:de28e92f43] Step4 é chamado. Ok. Só que eu não quero isso, eu quero que Step4 só entre quando todas as threads lançadas em StepRegistry terminarem, pois Step4 só pode ser executado quando StepRegistry terminar.
Resumindo eu quero um esquema assim (onde T1 é a linha principal e T2-T6, o processamento distribuído que quero fazer) ...
Em vez disso:
T2 -------------> T3 -------------> T4 -------------> T5 -------------> T6 -------------> T1 -------|-------|---------------> Step1 Step2 StepRegistry (T2-T6) Step4(T1)
Eu quero isso:
T2 -------------> T3 -------------> T4 -------------> T5 -------------> T6 -------------> T1 -------|-------| |-----------> Step1 Step2 StepRegistry Step4
Minha idéia inicial era parar a thread ´principal´ da aplicação. Mas não descobri como! Algo como Application.MainThread.Stop...
Agora o que tô pensando é em fazer o código que lança as threads ser o último da lista, ou seja, remover Step4. No código compartilhado pelas threads eu controlo quantas estão ativas e só executo Step4 após todas terminarem. Mas isso é meio gambiarrazinha. Tem um jeito, digamos, mais elegante?
Obrigado a todos!
Renatosilva
Curtir tópico
+ 0Posts
30/05/2005
Massuda
Gostei + 0
31/05/2005
Nildo
Uma solução seria você pegar o handle da thread do form principal, pelo [b:7964ebdb69]GetCurrentThread[/b:7964ebdb69] (executando esse código no Form principal), e usar as APIs [b:7964ebdb69]SuspendThread[/b:7964ebdb69] e [b:7964ebdb69]ResumeThread[/b:7964ebdb69] passando como parâmetro o código da thread.
Mas cuidado ao mecher com isso para não cair em DeadLock.
Ou então, você poderia colocar no OnTerminate da StepRegistry para executar o Step4.
Ps.: Gostei do modo que você interpreta seus problemas :)
Gostei + 0
31/05/2005
Nildo
Poderia criar um Handle qualquer e utilizar o WaitForSingleObject. Eu acho mais simples, mas eu acho que usando o OnTerminate fica mais facil para ele não cair em DeadLock
Gostei + 0
31/05/2005
Renatosilva
Quando mexer no programa dou um feedback do que consegui fazer. Obrigado!!!
Gostei + 0
31/05/2005
Nildo
Se você parar uma Thread que estava sincronizada com outra, que continua rodando, vai dar altos erros! hehehe
E você deve tomar cuidado pra não parar uma Thread que trata de resumir a execução de outras.
Resumidamente, você nao pode parar uma thread que é dependente de outras threads
Gostei + 0
01/06/2005
Beppe
´Sem´ é um campo no form do tipo THandle.
procedure TForm1.StepRegistry; const NumThreads = 5; var Falta: Integer; begin Sem := CreateSemaphore(nil, 0, 1, ´´); try Falta := NumThreads; // crie seus threads aqui while Falta > 0 do begin // espera por um thread terminar if WaitForSingleObject(Sem, 100) = WAIT_OBJECT_0 then Dec(Falta); // deixa a VCL tratar suas mensagens Application.ProcessMessages; end; finally CloseHandle(Sem); Sem := 0; end; end;
Cada thread deve executar este trecho de código ao terminar sua parte:
ReleaseSemaphore(Form1.Sem, 1, nil);
Gostei + 0
01/06/2005
Nildo
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)