2013-04-08 2 views
1

Это слегка модифицированный вариант одного из примеров программ дают в C# в двух словах:Thread.join() изменяет выход программы в C#

using System; 
using System.Threading; 

namespace SemaphorTest 
{ 
    class Program 
    { 
     static Semaphore gate = new Semaphore(3, 3); 
     static void Main(string[] args) 
     { 
      for (int i = 0; i < 5; i++) 
      { 
       Thread t = new Thread(Enter); 
       t.Start(i); 
      } 
     } 

     public static void Enter(Object id) 
     { 
      Console.WriteLine("Thread " + id + " wants to enter."); 
      gate.WaitOne(); 
      Console.WriteLine("Thread " + id + " is in."); 
      Thread.Sleep(500 * (Int32)id); 
      Console.WriteLine("Thread " + id + " leaving."); 
      gate.Release(); 
     } 
    } 
} 

Это печатает следующий вывод (казалось бы, в случайном порядке) :

Thread 0 wants to enter. 
Thread 1 wants to enter. 
Thread 1 is in. 
Thread 0 is in. 
Thread 2 wants to enter. 
Thread 3 wants to enter. 
Thread 0 leaving. 
Thread 3 is in. 
Thread 4 wants to enter. 
Thread 2 is in. 
Thread 1 leaving. 
Thread 4 is in. 
Thread 2 leaving. 
Thread 3 leaving. 
Thread 4 leaving. 

Однако добавление Thread.join() следующим образом изменяет выходную drastically.ie:

for (int i = 0; i < 5; i++) 
      { 
       Thread t = new Thread(Enter); 
       t.Start(i); 
       t.Join(); 
      } 

Изменяет вывод на:

Thread 0 wants to enter. 
Thread 0 is in. 
Thread 0 leaving. 
Thread 1 wants to enter. 
Thread 1 is in. 
Thread 1 leaving. 
Thread 2 wants to enter. 
Thread 2 is in. 
Thread 2 leaving. 
Thread 3 wants to enter. 
Thread 3 is in. 
Thread 3 leaving. 
Thread 4 wants to enter. 
Thread 4 is in. 
Thread 4 leaving. 

Почему это происходит? Я знаю, что эти потоки являются потоками переднего плана по умолчанию и что основному потоку не нужно ждать их завершения (они будут запускаться даже после завершения Main, поэтому они не потребуют thread.Join() здесь). Но я не понимаю, что заставляет их работать в порядке, так как они были созданы после изменения. Есть идеи ?

Thanks 
Dileep Balakrishnan 
+2

'Join()' делает однопоточное приложение. –

+2

'Join()' делает это * ведет себя так, как если бы это было * однопоточное приложение – spender

+0

@spender - указывая 't.Start(); t.Join(); 'оставляет очень мало места (времени) для любой многопоточности. Умный джиттер может даже оптимизировать это. –

ответ

8

Почему это происходит?

Потому что вы просили его!

Вы начали один поток, затем дождались его завершения, затем начали следующую цепочку и т. Д. Именно это делает Thread.Join: он блокирует текущий исполняемый поток, пока поток, который вы ему назвали, не прекращается.

Что мне нужно, так это то, что вы ожидали этого кода ... Если вы просто хотели дождаться окончания всех потоков, прежде чем разрешить основной поток, вам нужно запустить все потоки, вспоминая их, когда вы идете, и затем звоните Join на каждом по очереди. Например:

List<Thread> threads = new List<Thread>(); 
// First start all the threads 
for (int i = 0; i < 5; i++) 
{ 
    Thread t = new Thread(Enter); 
    t.Start(i); 
    threads.Add(t); 
} 

// Then wait for them to finish 
foreach (var thread in threads) 
{ 
    thread.Join(); 
} 
+0

Интересно, что я написал тот же код, как вы указали после прочтения своего сообщения (конечно, без ваших комментариев :)). Спасибо, в любом случае. –

1

Вы присоединяетесь к каждой теме с вызывающей нитью. Это по существу блокирует вызывающий поток и ждет по очереди каждого потока.

В documentation говорится:

Блокирует вызывающий поток до тех пор, пока поток прекращается.

0

Thread.join() не делает работу одновременно. Он фактически обеспечивает поведение, которое вы видите, блокируя текущий поток, пока он не будет завершен. Это четко указано в документации: http://msdn.microsoft.com/en-us/library/95hbf2ta.aspx