Страница 399 из 502
<b> static void Main() { </b>
<b> Console.WriteLine("Основной поток начат."); </b>
<b> // Сконструировать три потока. </b>
<b> MyThread mt1 = new MyThread("Потомок #1"); </b>
<b> MyThread mt2 = new MyThread("Потомок #2"); </b>
<b> MyThread mt3 = new MyThread("Потомок #3"); </b>
<b> do { </b>
<b> Console.Write("."); </b>
<b> Thread.Sleep(100); </b>
<b> } while (mt1.Thrd.IsAlive && </b>
<b> mt2.Thrd.IsAlive && </b>
<b> mt3.Thrd.IsAlive); </b>
<b> Console.WriteLine("Основной поток завершен."); </b>
<b> } </b>
<b>} </b>
При выполнении этой версии программы результат получается таким же, как и прежде. Единственное отличие заключается в том, что в ней используется свойство IsAlive для отслеживания момента окончания порожденных потоков.
Еще один способ отслеживания момента окончания состоит в вызове метода Join(). Ниже приведена его простейшая форма.
<b>public void Join()</b>
Метод Join() ожидает до тех пор, пока поток, для которого он был вызван, не завершится. Его имя отражает принцип ожидания до тех пор, пока вызывающий поток не присоединится к вызванному методу. Если же данный поток не был начат, то генерируется исключение ThreadStateException. В других формах метода Join() можно указать максимальный период времени, в течение которого следует ожидать завершения указанного потока.
В приведенном ниже примере программы метод Join() используется для того, чтобы основной поток завершился последним.
<b>// Использовать метод Join(). </b>
<b>using System; </b>
<b>using System.Threading; </b>
<b>class MyThread { </b>
<b> public int Count; </b>
<b> public Thread Thrd; </b>
<b> public MyThread(string name) { </b>
<b> Count = 0; </b>
<b> Thrd = new Thread(this.Run); </b>
<b> Thrd.Name = name; </b>
<b> Thrd.Start(); </b>
<b> } </b>
<b> // Точка входа в поток, </b>
<b> void Run() { </b>
<b> Console.WriteLine(Thrd.Name + " начат."); </b>
<b> do { </b>
<b> Thread.Sleep(500); </b>
<b> Console.WriteLine ("В потоке " + Thrd.Name + </b>
<b> ",</b><b> Count = " + Count); </b>
<b> Count++; </b>
<b> } while(Count < 10); </b>
<b> Console.WriteLine(Thrd.Name + " завершен."); </b>
<b> } </b>
<b>} </b>
<b>// Использовать метод Join() для ожидания до тех пор, </b>
<b>// пока потоки не завершатся, </b>
<b>class JoinThreads { </b>
<b> static void Main() { </b>
<b> Console.WriteLine("Основной поток начат."); </b>
<b> // Сконструировать три потока. </b>
<b> MyThread mt1 = new MyThread("Потомок #1"); </b>
<b> MyThread mt2 = new MyThread("Потомок #2"); </b>
<b> MyThread mt3 = new MyThread("Потомок #3"); </b>
<b> mt1.Thrd.Join(); </b>
<b> Console.WriteLine("Потомок #1 присоединен.");</b>
<b> mt2.Thrd.Join(); </b>
<b> Console.WriteLine("Потомок #2 присоединен.");</b>
<b> mt3.Thrd.Join(); </b>
<b> Console.WriteLine("Потомок #3 присоединен."); </b>
<b> Console.WriteLine("Основной поток завершен."); </b>
<b> }</b>
<b>}</b>
Ниже приведен один из возможных результатов выполнения этой программы. Напомним, что он может отличаться в зависимости от среды выполнения, операционной системы и прочих факторов, влияющих на выполнение программы.
<b>Основной поток начат.</b>
<b>Потомок #1 начат.</b>