Je peux voir 5 options disponibles:
1. Thread.Join
Comme pour la réponse de Mitch. Mais cela bloquera votre thread d'interface utilisateur, mais vous obtenez un délai d'expiration intégré pour vous.
2. Utilisez un WaitHandle
ManualResetEvent
est un WaitHandle
comme jrista suggéré.
Une chose à noter est que si vous souhaitez attendre plusieurs threads, WaitHandle.WaitAll()
cela ne fonctionnera pas par défaut, car il a besoin d'un thread MTA. Vous pouvez contourner ce problème en marquant votre Main()
méthode avec MTAThread
- cependant, cela bloque votre pompe de message et n'est pas recommandé d'après ce que j'ai lu.
3. Déclenchez un événement
Voir cette page de Jon Skeet sur les événements et le multi-threading, il est possible qu'un événement puisse devenir désabonné entre le if
et le EventName(this,EventArgs.Empty)
- cela m'est déjà arrivé.
(J'espère que ces compilent, je n'ai pas essayé)
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. Utilisez un délégué
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();
}
}
}
Si vous utilisez la méthode _count, il peut être judicieux (pour être sûr) de l'incrémenter en utilisant
Interlocked.Increment(ref _count)
Je serais intéressé de connaître la différence entre l'utilisation de délégués et d'événements pour la notification de thread, la seule différence que je sais est que les événements sont appelés de manière synchrone.
5. Faites-le plutôt de manière asynchrone
La réponse à cette question a une description très claire de vos options avec cette méthode.
Délégué / Événements sur le mauvais fil
La façon de faire les événements / délégués signifie que votre méthode de gestionnaire d'événements est sur thread1 / thread2 et non sur le thread d'interface utilisateur principal , vous devrez donc revenir en haut des méthodes HandleThreadDone:
// Delegate example
if (InvokeRequired)
{
Invoke(new Action(HandleThreadDone));
return;
}