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
é um WaitHandle
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 seu Main()
método com MTAThread
- 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)
public class Form1 : Form
{
int _count;
void ButtonClick(object sender, EventArgs e)
{
ThreadWorker worker = new ThreadWorker();
worker.ThreadDone += HandleThreadDone;
Thread thread1 = new Thread(worker.Run);
thread1.Start();
_count = 1;
}
void HandleThreadDone(object sender, EventArgs e)
{
// You should get the idea this is just an example
if (_count == 1)
{
ThreadWorker worker = new ThreadWorker();
worker.ThreadDone += HandleThreadDone;
Thread thread2 = new Thread(worker.Run);
thread2.Start();
_count++;
}
}
class ThreadWorker
{
public event EventHandler ThreadDone;
public void Run()
{
// Do a task
if (ThreadDone != null)
ThreadDone(this, EventArgs.Empty);
}
}
}
4. Use um delegado
public class Form1 : Form
{
int _count;
void ButtonClick(object sender, EventArgs e)
{
ThreadWorker worker = new ThreadWorker();
Thread thread1 = new Thread(worker.Run);
thread1.Start(HandleThreadDone);
_count = 1;
}
void HandleThreadDone()
{
// As before - just a simple example
if (_count == 1)
{
ThreadWorker worker = new ThreadWorker();
Thread thread2 = new Thread(worker.Run);
thread2.Start(HandleThreadDone);
_count++;
}
}
class ThreadWorker
{
// Switch to your favourite Action<T> or Func<T>
public void Run(object state)
{
// Do a task
Action completeAction = (Action)state;
completeAction.Invoke();
}
}
}
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:
// Delegate example
if (InvokeRequired)
{
Invoke(new Action(HandleThreadDone));
return;
}