Eu realmente nunca usei threading antes em C #, onde preciso ter dois threads, bem como o thread principal da interface do usuário. Basicamente, eu tenho o seguinte.
public void StartTheActions()
{
//Starting thread 1....
Thread t1 = new Thread(new ThreadStart(action1));
t1.Start();
// Now, I want for the main thread (which is calling `StartTheActions` method)
// to wait for `t1` to finish. I've created an event in `action1` for this.
// The I wish `t2` to start...
Thread t2 = new Thread(new ThreadStart(action2));
t2.Start();
}
Então, essencialmente, minha pergunta é como fazer com que um thread aguarde o término de outro. Qual é a melhor maneira de fazer isso?
c#
multithreading
Maxim Zaslavsky
fonte
fonte
Respostas:
Eu posso ver 5 opções disponíveis:
1. Thread.Join
Como na resposta de Mitch. Mas isso bloqueará o encadeamento da interface do usuário, no entanto, você obtém um tempo limite incorporado para você.
2. Use um
WaitHandle
ManualResetEvent
é umWaitHandle
como jrista sugeriu.Uma coisa a ser observada é que, se você deseja esperar por vários threads,
WaitHandle.WaitAll()
não funcionará por padrão, pois precisa de um thread MTA. Você pode contornar isso marcando seuMain()
método comMTAThread
- no entanto, isso bloqueia sua bomba de mensagens e não é recomendado pelo que li.3. Dispare um evento
Consulte esta página de Jon Skeet sobre eventos e multiencadeamento, é possível que um evento possa ser cancelado de inscrição entre o
if
e oEventName(this,EventArgs.Empty)
- já aconteceu comigo antes.(Espero que estes compilem, eu não tentei)
4. Use um delegado
Se você usar o método _count, pode ser uma ideia (para ser seguro) incrementá-lo usando
Interlocked.Increment(ref _count)
Eu estaria interessado em saber a diferença entre o uso de delegados e eventos para notificação de threads, a única diferença que eu sei são os eventos que são chamados de forma síncrona.
5. Faça de forma assíncrona
A resposta a esta pergunta tem uma descrição muito clara de suas opções com este método.
Delegar / Eventos no segmento errado
A maneira de fazer o evento / delegar significa que o método do manipulador de eventos está no thread1 / thread2 e não no thread da interface principal da interface do usuário ; portanto, você precisará voltar à parte superior dos métodos HandleThreadDone:
fonte
Adicionar
depois de iniciá-lo, mas isso não resultará muito, pois é essencialmente o mesmo resultado que a execução no thread principal!
Eu recomendo a leitura de e-book gratuito Threading em C #, de Joe Albahari , se você quiser obter uma compreensão do threading no .NET.
fonte
Join
seja literalmente o que o solicitante parece estar pedindo, isso pode ser extremamente ruim em geral. Uma chamada paraJoin
desligará o encadeamento a partir do qual isso está sendo feito. Se esse for o principal thread da GUI, isso é RUIM ! Como usuário, detesto ativamente aplicativos que parecem funcionar dessa maneira. Portanto, consulte todas as outras respostas a esta pergunta e stackoverflow.com/questions/1221374/…As duas respostas anteriores são ótimas e funcionarão para cenários simples. Existem outras maneiras de sincronizar threads, no entanto. O seguinte também funcionará:
ManualResetEvent é um dos vários WaitHandle que a estrutura .NET tem a oferecer. Eles podem fornecer recursos de sincronização de encadeamento muito mais avançados do que as ferramentas simples, mas muito comuns, como lock () / Monitor, Thread.Join etc. Eles também podem ser usados para sincronizar mais de dois encadeamentos, permitindo cenários complexos, como um encadeamento 'mestre' que coordena vários segmentos 'filhos', vários processos simultâneos que dependem de vários estágios um do outro para serem sincronizados etc.
fonte
Se estiver usando do .NET 4, este exemplo pode ajudá-lo:
from: https://stackoverflow.com/a/4190969/1676736
fonte
Você deseja o
Thread.Join()
método ou uma de suas sobrecargas .fonte
Gostaria que seu thread principal passasse um método de retorno de chamada para o seu primeiro thread e, quando terminado, invocaria o método de retorno de chamada no mainthread, que pode iniciar o segundo thread. Isso evita que o encadeamento principal fique travado enquanto aguarda um Join ou Waithandle. Passar métodos como delegados é uma coisa útil para aprender com C # de qualquer maneira.
fonte
Tente o seguinte:
fonte
Postar para talvez ajudar outras pessoas, gastou bastante tempo procurando uma solução como a que eu vim. Então, adotei uma abordagem um pouco diferente. Existe uma opção de contador acima, apenas a apliquei de maneira um pouco diferente. Eu estava gerando vários threads e incrementando um contador e diminuindo o contador quando um thread começou e parou. Então, no método principal, eu queria pausar e aguardar a conclusão dos threads.
Documentado no meu blog. http://www.adamthings.com/post/2012/07/11/ensure-threads-have-finished-before-method-continues-in-c/
fonte
Quando quero que a interface do usuário consiga atualizar sua exibição enquanto aguarda a conclusão de uma tarefa, uso um loop while que testa IsAlive no thread:
fonte
Aqui está um exemplo simples que aguarda a conclusão de uma banda de rodagem, dentro da mesma classe. Também faz uma chamada para outra classe no mesmo espaço para nome. Incluí as instruções "using" para que ele possa ser executado como um Winform, desde que você crie o button1.
fonte