multithreading:我什么时候可以使用Join?

我在网上看到它说我使用myThread.Join(); 当我想阻止我的线程,直到另一个线程完成。 (我不知道这件事情之一是如果我有多个线程)。

但是一般来说,当我使用.Join()或者对它有用的条件时,我就不会得到。 任何人都可以解释这个给我,就像我是四年级的? 很简单的理解解释会得到我的答案。

假设你想要启动一些工作线程来执行某种计算,然后用所有结果做一些事情。

 List<Thread> workerThreads = new List<Thread>(); List<int> results = new List<int>(); for (int i = 0; i < 5; i++) { Thread thread = new Thread(() => { Thread.Sleep(new Random().Next(1000, 5000)); lock (results) { results.Add(new Random().Next(1, 10)); } }); workerThreads.Add(thread); thread.Start(); } // Wait for all the threads to finish so that the results list is populated. // If a thread is already finished when Join is called, Join will return immediately. foreach (Thread thread in workerThreads) { thread.Join(); } Debug.WriteLine("Sum of results: " + results.Sum()); 

哦,是的,不要使用这样的随机数,我只是想写一个最小的,容易理解的例子。 如果你创build新的Random实例的时间太近,那么结果并不是随机的,因为种子是基于时钟的。

在下面的代码片断中,主线程调用Join() ,使其等待所有派生线程完成:

 static void Main() { Thread regularThread = new Thread(ThreadMethod); regularThread.Start(); Thread regularThread2 = new Thread(ThreadMethod2); regularThread2.Start(); // Wait for spawned threads to end. regularThread.Join(); Console.WriteLine("regularThread returned."); regularThread2.Join(); Console.WriteLine("regularThread2 returned."); } 

请注意,如果您还从线程池中分离了一个线程(例如使用QueueUserWorkItem),则Join不会等待该后台线程。 您将需要实现一些其他机制,如使用AutoResetEvent。

对于线程的一个很好的介绍,我推荐阅读Joe Albahari的免费线程在C#

Join主要用于当你需要等待一个线程(或一堆线程)在程序继续之前终止。

因为这个原因,当你需要从一个线程执行中收集结果时,它也特别有用。

根据下面的Arafangion评论,如果在创build线程之后需要执行一些清理/内务pipe理代码,则join线程也很重要。

这是非常简单的程序来演示使用线程Join 。请按照我的意见更好的理解。写这个程序,因为它是。

  using System; using System.Threading; namespace ThreadSample { class Program { static Thread thread1, thread2; static int sum=0; static void Main(string[] args) { start(); Console.ReadKey(); } private static void Sample() { sum = sum + 1; } private static void Sample2() { sum = sum + 10; } private static void start() { thread1 = new Thread(new ThreadStart(Sample)); thread2 = new Thread(new ThreadStart(Sample2)); thread1.Start(); thread2.Start(); // thread1.Join(); // thread2.Join(); Console.WriteLine(sum); Console.WriteLine(); } } } 

1.首次运行(带注释)结果为0(初始值)或1(线程1完成)或10(或线程完成)

2.运行删除注释thread1.Join()结果应该总是大于1.因为thread1.Join()被触发,并且线程1应该在得到总和之前完成。

运行删除所有评论结果应该总是11

在方法“Sample”中添加300ms的延迟,从devopsEMK的文章中的“Sample2”中延迟400ms会使其更容易理解。

通过这样做,您可以观察到通过从“thread1.Join();”中删除注释 线,主线程等待“线程1”完成,只有在移动之后。

另一个例子,当你的工作线程让我们说从一个inputstream中读取,而read方法可以永远运行,你想以某种方式避免这种情况 – 通过使用另一个看门狗线程应用超时:

 // worker thread var worker = new Thread(() => { Trace.WriteLine("Reading from stream"); // here is the critical area of thread, where the real stuff happens // Sleep is just an example, simulating any real operation Thread.Sleep(10000); Trace.WriteLine("Reading finished"); }) { Name = "Worker" }; Trace.WriteLine("Starting worker thread..."); worker.Start(); // watchdog thread ThreadPool.QueueUserWorkItem((o) => { var timeOut = 5000; if (!worker.Join(timeOut)) { Trace.WriteLine("Killing worker thread after " + timeOut + " milliseconds!"); worker.Abort(); } });