Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

Sign in to follow this  
softklin

Threads - continuar execução quando as outras threads terminarem

Recommended Posts

softklin

Boas pessoal.

Estou aqui a trabalhar um mini-projecto antigo, que tem como objectivo verificar numa lista de links, quais os que estão "mortos". Para tal, resolvi incluir uma pequena funcionalidade no programa, que é um limite de ligações. Como já devem ter adivinhado, estou a fazer com threads, e é aí que tenho o problema.

Basicamente, estou a fazer uma thread por link, com auxilio de um semáforo 'sem' para limitar o número de threads concorrentes e de outro semáforo 'allDone' que irá ser libertado quando todos os links forem verificados:

                // inicializar o semaforo que controla nº threads concorrentes
                int totalCon = (int) numMaxCon.Value;
                sem = new Semaphore(totalCon, totalCon);

                // inicializações...

                foreach (String uri in urlList)
                {                  
                    new Thread(checkUrl).Start(uri);
                }
                
                // aguardar que todas as threads tenham terminado
                allDone.WaitOne();

                fileWrite.Close();
                // mostrar resultados...

A função checkurl, resumidamente, é:

       private void checkUrl(object url)
        {
            // aguardar pelo semaforo
            sem.WaitOne();

            // obter resultados aqui...

            // libertar semaforo allDone quando todos os pedidos forem concluidos
            lock (this)
            {
                jobsDone++;

                if (jobsDone == totalJobs)
                    allDone.Release();
            }

            // libertar semaforo
            sem.Release();
        }

O que me acontece é que o processo fica bloqueado no allDone.WaitOne(), pois se verificar em Debug, o total de trabalhos nunca chega ao total da lista. Já verifiquei as inicializações, e à partida, não deveria falhar. Já andei também à procura do reportProgress ou similar, e não encontro na Thread.

Alguém tem alguma sugestão do que possa estar a fazer mal?


Nick antigo: softclean | Tens um projeto? | Wiki P@P

Ajuda a comunidade! Se encontrares algo de errado, usa a opção "Denunciar" por baixo de cada post.

Share this post


Link to post
Share on other sites
DVD

Duas questões:

- Não estás a usar o allDone para mais nada?

- Já viste se as threads estão a terminar todas ou estão presas em algum lugar?

Quanto à primeira questão, se não usares para mais nada escusas de estar a por codigo no checkurl, usa as proprias threads para sincronizar aka join :)

Quanto à segunda parece-me que seja o que está a acontecer

Share this post


Link to post
Share on other sites
softklin

Boas DVD, obrigado pela ajuda. O allDone seria um semáforo para controlar quando todas as threads teriam feito o trabalho, mas olhando bem, o incremento não seria thread-safe.

Resolvi usar a tua sugestão dos joins, e ficou da seguinte maneira:

                Thread[] jobs = new Thread[urlList.Length];
                int i = 0;
                foreach (String uri in urlList)
                {                  
                    jobs[i] = new Thread(checkUrl);
                    jobs[i].Start(uri);
                    i++;
                }

                // garantir que todas as threads são executadas antes de avançar
                foreach (Thread t in jobs)
                {
                    t.Join();
                }

Ou seja, basicamente, faço um join por cada thread que executo depois de as lançar, para continuar o código apenas após a execução de todas as threads. Esse problema penso estar resolvido.

Já agora, há problemas de criar tantas threads quanto número de links a verificar? No exemplo que testei, tentei com cerca de 300 links e foi esse o número de threads aberto, agora não sei se haverá alguma implicação em termos de recursos, tens algum conselho neste caso?


Nick antigo: softclean | Tens um projeto? | Wiki P@P

Ajuda a comunidade! Se encontrares algo de errado, usa a opção "Denunciar" por baixo de cada post.

Share this post


Link to post
Share on other sites
softklin

Obrigado pela dica bruno1234, mas neste exemplo, como não queria complicar muito, limitei-me a fazer uma coisa muito simples: em vez de criar as threads todas e bloqueá-las após terem sido criadas, resolvi bloquear no momento imediatamente antes da sua criação, no ciclo for. Ficou:

                Thread[] jobs = new Thread[urlList.Length];
                int i = 0;
                foreach (String uri in urlList)
                {        
                    // aguardar pelo semaforo
                    sem.WaitOne();

                    jobs[i] = new Thread(checkUrl);
                    jobs[i].Start(uri);
                    i++;
                }

                // garantir que todas as threads são executadas antes de avançar
                foreach (Thread t in jobs)
                {
                    t.Join();
                }

O número de threads concorrentes fica igual ao número de ligações simultâneas.


Nick antigo: softclean | Tens um projeto? | Wiki P@P

Ajuda a comunidade! Se encontrares algo de errado, usa a opção "Denunciar" por baixo de cada post.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.