11

私の同僚が私たちのコードに問題を発見し、何が起こっているのかを正確に突き止めるのにしばらく時間がかかりましたが、次の簡単な例で最もよく実証できます:

// 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();
    }
}

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

4

2 に答える 2

5

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

于 2013-01-17T17:04:22.660 に答える
5

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

  • を開始する前に、コンソールの出力に対して何らかの操作を行っていれば問題ありませんReadKey。これにはフェッチConsole.Outが含まれますが、使用は含まれません
  • Console.WriteLine通話が通話の前に開始されるように遅延を入れても問題ありません (また、が待機しているConsole.ReadKeyに複数のWriteLine通話を行うことができます)。 ReadKey

コンソールを使用する最初の操作は初期化のためにロックを取得し (2 回初期化されるのを避けるため)、ReadKeyメソッドはキーが読み取られるまでロックを保持していると思われます。それは確かに私がこれまでに実行したすべてのプログラムを説明するでしょう.

ただし、仮定された初期化を実行する操作は興味深いものです。Console.Out読み取りは問題を「修正」しますが、からの読み取りはそうでConsole.Inはありません。

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

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

于 2013-01-17T17:10:21.423 に答える