Aguarde dois segmentos para terminar

Se você tiver um thread principal que inicia dois outros threads. Qual é a maneira mais limpa de fazer o thread principal esperar pelos dois outros threads?

Eu poderia usar o bgndworker e o sleep spinner que verificam tanto o IsBusy dos trabalhadores da bgnd, mas eu acho que há uma maneira melhor.

EDIT Mais alguns requisitos:

  • O thread principal tem algum outro trabalho para fazer (por exemplo, GUI).
  • Os dois segmentos gerados devem poder reportar exceções e retornar valores de resultados

Veja as respostas neste tópico . Eu gosto dessa opção;

Forker p = new Forker(); p.Fork(delegate { DoSomeWork(); }); p.Fork(delegate { DoSomeOtherWork(); }); p.Join(); 

Re retornando valores / relatando exceções – faça com que cada garfo faça isso como um retorno de chamada no final da lógica … (você pode usar variables ​​capturadas para passar o estado para ambos os garfos, incluindo um registrador compartilhado, etc.).

Exemplo rápido usando Thread.Join ();

  Thread t1 = new Thread(new ThreadStart(delegate() { System.Threading.Thread.Sleep(2000); })); Thread t2 = new Thread(new ThreadStart(delegate() { System.Threading.Thread.Sleep(4000); })); t1.Start(); t2.Start(); t1.Join(); t2.Join(); 

EDIT Outro exemplo 3 usando Wait Handles:

  ManualResetEvent[] waitHandles = new ManualResetEvent[]{ new ManualResetEvent(false), new ManualResetEvent(false) }; Thread t1 = new Thread(new ParameterizedThreadStart(delegate(object state) { ManualResetEvent handle = (ManualResetEvent)state; System.Threading.Thread.Sleep(2000); handle.Set(); })); Thread t2 = new Thread(new ParameterizedThreadStart(delegate(object state) { ManualResetEvent handle = (ManualResetEvent)state; System.Threading.Thread.Sleep(4000); handle.Set(); })); t1.Start(waitHandles[0]); t2.Start(waitHandles[1]); WaitHandle.WaitAll(waitHandles); Console.WriteLine("Finished"); 
 thread1.Join(); thread2.Join(); 

Além das outras respostas … uma alternativa para “iniciar dois encadeamentos e esperar que ambos terminem” é “iniciar um encadeamento e fazer um trabalho sozinho, depois esperar que o outro encadeamento termine”.

Claro, se você quiser iniciar dois trabalhos, trabalhe um pouco mais no thread principal e aguarde os dois outros threads terminarem, o que não funciona tão bem.

EDIT: Se o thread principal é um segmento de interface do usuário, você não deve estar bloqueando o acabamento de outros segmentos – você deve (IMO) fazê-los chamar de volta ao thread principal quando eles terminarem. Dessa forma, você ainda terá uma interface do usuário responsiva enquanto está sendo executada.

Você não pode esperar pelo acabamento e ter a GUI utilizável. A melhor abordagem para isso é gerar threads e usar events para se comunicar com a GUI. Lembre-se de que, no manipulador de events, você não pode modificar o controle. Em vez de fazê-lo diretamente, use o método Invoke.

WaitHandle.WaitAny é seu amigo. Ele permite que você espere em vários segmentos ou outros tipos de objects a serem sinalizados.

http://msdn.microsoft.com/pt-br/library/tdykks7z.aspx

EDITAR:

Na verdade, WaitHandle.WaitAll é o que você quer, não WaitAny.

http://msdn.microsoft.com/pt-br/library/system.threading.waithandle.waitall.aspx

EDITAR:

O método Join alguma menção é ok, mas uma desvantagem é que não é uma operação completamente atômica. Isso pode ou não ser importante para você, no entanto.