在继续之前如何等待线程完成?

时间:2020-03-05 18:38:46  来源:igfitidea点击:

我有一些代码可以在.NET CF 2.0上启动线程:

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

如果我在循环中调用它,则项目将不按顺序完成。如何在t.Start()之后引入等待,以便线程的工作在代码继续之前完成?比手动创建线程,BeginInvoke / EndInvoke会是更好的选择吗?

解决方案

回答

如果我正确地阅读了这篇文章,那么我们正在启动一堆线程上的工作项,但是我们担心这些线程会无序地完成工作,并且宁愿等到每个线程按照它们的启动顺序来完成工作?

如果是这种情况,那么我不确定为什么要为每个工作项创建一个线程。也许你可以扩大?

如果确实需要等待线程完成,则可以执行以下操作:

t.Join();

回答

我们需要在线程上施加多少顺序?如果我们只需要在循环中开始的所有工作在代码继续之前完成,但是我们不关心循环中工作的完成顺序,那么调用Join是答案。要在Kevin Kenny的答案中添加更多细节,我们应该在循环外调用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,则结果基本上与完全不使用线程相同。循环主体的每次迭代都会创建并启动一个线程,但随后立即将其加入并等待其完成。

如果各个线程产生某种结果(例如,在日志中写一条消息),则消息可能仍会出现乱序,因为线程之间没有协调。通过与Monitor协调,可以使线程按顺序输出结果。

回答

等待线程完成的另一种方法是使用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();
}