Как дождаться завершения потока перед продолжением?

У меня есть код для запуска потока на .NET CF 2.0:

ThreadStart tStart = new ThreadStart(MyMethod);
Thread t = new Thread(tStart);
t.Start();

Если я вызываю это внутри цикла, элементы полностью не в порядке. Как ввести ожидание после t.Start(), чтобы работа над потоком завершилась до продолжения кода? Будет ли BeginInvoke / EndInvoke лучшим вариантом для этого, чем создание потоков вручную?

Ответов (3)

Решение

Какой порядок нужно наложить на нити? Если вам просто нужно, чтобы вся работа, начатая в цикле, была завершена до продолжения выполнения кода, но вам не важен порядок завершения работы в цикле, то ответом будет вызов Join. Чтобы добавить больше деталей к ответу Кевина Кенни, вы должны вызвать Join вне цикла. Это означает, что вам понадобится коллекция для хранения ссылок на запущенные вами потоки:

// Start all of the threads.
List<Thread> startedThreads = new List<Thread>();
foreach (...) {
  Thread thread = new Thread(new ThreadStart(MyMethod));
  thread.Start();
  startedThreads.Add(thread);
}

// Wait for all of the threads to finish.
foreach (Thread thread in startedThreads) {
  thread.Join();
}

Напротив, если вы вызываете Join внутри цикла, результат будет таким же, как если бы вы вообще не использовали потоки. Каждая итерация тела цикла будет создавать и запускать поток, но затем сразу же присоединяться к нему и ждать его завершения.

Если отдельные потоки дают какой-то результат (например, записывают сообщение в журнал), то сообщения все равно могут отображаться не по порядку, потому что между потоками нет координации. Можно заставить потоки выводить свои результаты по порядку, скоординировав их с монитором.

Если я правильно это читаю, вы запускаете рабочие элементы в группе потоков, но вас беспокоит, что потоки завершаются не по порядку, и вы бы предпочли подождать, пока каждый поток завершится в том порядке, в котором они были запущены?

Если это так, то я не уверен, зачем вы создаете поток для каждого рабочего элемента. Может быть, ты мог бы расшириться?

Если вам нужно дождаться завершения потока, вы можете просто сделать:

t.Join();

Another way of waiting for a thread to finish is using an AutoResetEvent .

private readonly AutoResetEvent mWaitForThread = new AutoResetEvent(false);

private void Blah()
{
    ThreadStart tStart = new ThreadStart(MyMethod);
    Thread t = new Thread(tStart);
    t.Start();

    //... (any other things)
    mWaitForThread.WaitOne();
}

private void MyMethod()
{
     //... (execute any other action)
     mWaitForThread.Set();
}