2013-01-17 11 views
11

私の同僚が私たちのコードに問題を発見しました。何が起こっているかを正確に把握するのに時間がかかりましたが、この単純な例で最もよく説明できます:Task.Run()を使用してコンソールに書き込むことができません

// Fails 
class Program 
{ 
    static void Main(string[] args) 
    { 
     Task.Run(() => Console.WriteLine("Hello World")); 
     Console.ReadKey(); 
    } 
} 

// Works fine 
class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.Write(String.Empty); 
     Task.Run(() => Console.WriteLine("Hello World")); 
     Console.ReadKey(); 
    } 
} 

メインスレッドのどこからでもコンソールに書き込むことで、バックグラウンドスレッドもコンソールに書き込むことができますが、なぜこのようなことが起こっているのかを理解することは苦労しています。誰もがメインスレッドからコンソールへの書き込みが、最初のスニペットが達成していないことを説明することはできますか?

+0

失敗したケースで何が起こったのか説明していません。私の箱には、あなたが帰ってくるまで掛けているように見えます。その時点で、それは印刷されます。 –

+0

@JonSkeetはい、それは私が見る動作です – kevinawalker

答えて

4

私は何が起こっているのか疑いがあります。私が観察したもの:

  • あなたがReadKeyを開始する前に、コンソールの出力とを行う場合、それは大丈夫です。これは、あなたがそうWriteLineConsole.WriteLineコール開始Console.ReadKeyコールの前に、それは大丈夫です(とあなたが複数を持つことができるという点で遅れを置く場合ReadKey
を待っている間 を呼び出し
  • それを使用してConsole.Outのフェッチではなく含み

    私はコンソールを使用する最初の操作が初期化(2回初期化されないように)を取得し、ReadKeyメソッドが鍵が読み取られるまでロックを保持していると思われます。私がこれまで走ってきたすべてのプログラムを忘れないでください。

    仮説初期化を実行する操作は興味深いものですが、Console.Outを読むと問題が「修正」されますが、Console.Inから読み取ることはできません。

    私は、ReadKeyがまだ値がコンソールにエコーされているため出力を初期化していると思われますが、私はそれに誓いたくありません。

    興味深いことに、Console.ReadKey()の代わりにConsole.ReadLine()を使用しても問題はありません。

  • +0

    'Console.ReadLine()'は同じ問題を引き起こさないことは間違いありません。時間をとってくれてありがとう – kevinawalker

    4

    実際、最初のケースは失敗しません。アプリケーションが終了する直前に「Hello World」が表示されます。これは古典的なRace Conditionです。最初のケースでは、メインスレッドのConsole.ReadKey()がタスクに勝利し、2番目のケースでは、タスクが勝ちます。残念なことに、私は空文字列を書くことでなぜタスクが勝つのか正確には言えません。

    +0

    これは確かに解決策です。 –

    +0

    私はこれが正しいとは思わない。 Console.ReadLineの呼び出しが完了した後にConsole.WriteLineが呼び出されたようなことではありません。*完了していなければ、しばらく待つと出力が表示されます。それは初期化問題のいくつかの並べ替えのように見えます、と私は思います。 –

    +0

    また、明確にするために、私はそれが競合状態だと信じていますが、どちらの呼び出しが*最初に開始されるかという点と、 'Console.ReadKey'がコンソールへの最初の呼び出しであり、どちらもその答えではっきりしていない場合のみです。 –

    関連する問題