Я бачу доступні 5 варіантів:
1. Нитка
Як і у відповіді Мітча. Але це заблокує ваш потік користувальницького інтерфейсу, проте ви отримаєте вбудований для вас тайм-аут.
2. Використовуйте a WaitHandle
ManualResetEvent
є, WaitHandle
як запропонував jrista.
Варто зазначити, що якщо ви хочете зачекати кілька потоків, WaitHandle.WaitAll()
за замовчуванням не працюватиме, оскільки для цього потрібен потік MTA. Ви можете подолати це, позначивши свій Main()
метод із MTAThread
- однак це блокує ваш набір повідомлень і не рекомендується з того, що я прочитав.
3. Пожежа подія
Ознайомтеся з цією сторінкою Джона Скіта про події та багатопотокові передачі, можливо, подія може скасувати підписку між if
та між EventName(this,EventArgs.Empty)
- це сталося зі мною раніше.
(Сподіваюся, ці компіляції я не пробував)
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. Використовуйте делегата
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();
}
}
}
Якщо ви використовуєте метод _count, можливо, ідея (щоб бути безпечною) збільшувати його за допомогою
Interlocked.Increment(ref _count)
Мені було б цікаво знати різницю між використанням делегатів та подіями для сповіщення про потоки. Єдина відома мені різниця - події називаються синхронно.
5. Зробіть це замість асинхронно
У відповіді на це питання дуже чіткий опис ваших варіантів цього методу.
Делегат / Події в неправильній темі
Подія / делегатний спосіб виконання дій означатиме, що ваш метод обробника подій знаходиться на thread1 / thread2, а не на основній нитці інтерфейсу користувача , тому вам потрібно буде переключитися назад праворуч у верхній частині методів HandleThreadDone:
// Delegate example
if (InvokeRequired)
{
Invoke(new Action(HandleThreadDone));
return;
}