2011-12-18 8 views
0

.NET ThreadPoolにはa sample on MSDNがあります。このコードを実行すると、出力が完全に不安定になることがあります。コンソール上で完全に空の出力が得られることがあります。.NET、x64でConsole.WriteLineマルチスレッド出力が空です。

Thread.Sleep()コールを追加すると、わずか数ミリ秒でも出力は正常です。

AFAIK Console.WriteLine()はスレッドセーフなので、出力は常にそこにあるはずです。しかし、少なくとも私のi7 2600 x64コンパイルされたバージョンではない。明らかに、ブレークポイントを追加するとすべてが問題ありませんが、それは私を怒らせます。

私はConcurrentBagを追加してものがあることを確認しましたが、その要素を印刷することさえ空です。繰り返しますが、ブレークポイントを追加するとすべてが問題ありません。

{ 
    public class TaskInfo 
    { 
     public string m_text; 

      public int m_value; 
     public ConcurrentBag<int> m_bag; 
    public TaskInfo(string text, int value, ConcurrentBag<int> bag) 
    { 
     m_text = text; 
     m_value = value; 
     m_bag = bag; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Program p = new Program(); 
     p.Run(); 
    } 

    void Run() 
    { 
     ConcurrentBag<int> concurrentBag = new ConcurrentBag<int>(); 
     for (int i = 0; i < 10; i++) 
     { 
      TaskInfo ti = new TaskInfo("Hello Thread", i, concurrentBag); 
      bool b = ThreadPool.QueueUserWorkItem(new WaitCallback(MyThreadFunction), ti); 
      if (!b) 
      { 
       Console.WriteLine("Damn!"); 
      } 
      //Thread.Sleep(5); 
     } 

     for (int j = 0; j < concurrentBag.Count; j++) 
     { 
      Console.WriteLine("This is in the bag: {0}", concurrentBag.ElementAt(j)); 
     } 
    } 

    static void MyThreadFunction(object stateInfo) 
    { 
     TaskInfo ti = (TaskInfo)stateInfo; 
     ti.m_bag.Add(ti.m_value); 
     Console.WriteLine(ti.m_text + ti.m_value.ToString()); 
    } 
} 

}

+0

サンプルにリンクできますか? –

+0

http://msdn.microsoft.com/en-us/library/kbf0f1ct(v=vs.80).aspx –

答えて

1

出力が空である可能性が非常によくわかります。

キューで10個のジョブをプッシュした後、すぐにが結果を消費し始めます。すべての仕事が終了するわけではなく、まだ開始されていない可能性もあります。

デバッガで実行すると、プログラムはMyThreadFunctionからWrtieLine()を見る前に終了します。

+0

true。私は元のソースを読んだだけで、コメントと余分なsleep()もあるので、メインスレッドはバックグラウンドスレッドが終了する前に終了します。ありがとう! –

0

あなたがそれらによって「生産」何かを印刷しようとするまで、(彼らは仕上げまで待つ)あなたがスレッドを作成するときに、あなたがそれらを結合する必要があること、それはありませんか?

もしそうでなければ、最後のループの前にスレッドを切り替えることができるスケジューラに頼っています。Runです。そうでない場合は、の前に最後のループでが実行されます。

一方、Thread.Sleepは、スケジューラを即座に他のスレッドに切り替えることができます。これはおそらくThread.Sleepの問題がないことを確認しているからでしょう。

1

これは明らかにコンソールアプリケーションです。すべての作業項目をキューに入れた後、Runメソッドが返され、プログラムはただちに終了します。あなたの作業項目が終了するのを待つことはありません。最低でも、実行後にThread.Sleepを追加して、スレッドプールが完了できるようにします。

正しいことは、ManualResetEventのインスタンスの配列を使用して、各ワーカースレッドによってすべてがSetになるのを待つことです。これはコンソールアプリケーションなので、Mainメソッドを[STAThread]で飾らない限り、WaitHandle.WaitAllを使用することはできません。

関連する問題