4

私は最近、C# の新しい async/await と Task.Run 機能に頭を悩ませようとしています。そうすることで、コンソールに書き込みを行う簡単なテスト コードを作成して、物事がどのような順序で発生するかを確認できるようにしました。

これが私のテストの1つです

[Test]
public void TaskRun()
{
    Console.WriteLine("Before");
    Task.Run(() => Console.WriteLine(_terminator.IWillBeBack()));
    Console.WriteLine("After");
}

次の Terminator クラスを使用します。

public class Terminator
{
    public string IWillBeBack()
    {
        return "I will be back";
    }
}

このことから、結果はおそらくBeforeAfter、そしてI will be back になると予想しました。これは実際に起こることです。次に、IWillBeBack メソッドを変更して、3 秒間スリープできるようにします。このためのコード:

public class Terminator
{
    public string IWillBeBack()
    {
        Thread.Sleep(3000);
        return "I will be back";
    }
}

結果はまだBeforeAfterであり、3 秒後に再びI will be back になると予想していました。しかし、これは起こることではありません。代わりにBeforeAfterを取得しますが、決して戻ることはありません。

どうしてこれなの?

デバッグすると、明らかにコードを通過し、スリープして戻ります。この方法では、プロダクション コードでは Thread.Sleep は必要ありませんが、2 番目のケースではコンソールに書き込まれない理由を漠然と理解したいと思います。

4

2 に答える 2

8

「Iwillback」を印刷する前に、テストが完了しています。それが終わるまで待つことは何もしていません。ただし、テストランナーによってはConsole.WriteLine、テストが終了するとすぐにリダイレクトが切断されている場合があります。

終了を確認したい場合は、テストを次のように変更してください。

[Test]
public void TaskRun()
{
    Console.WriteLine("Before");
    var task = Task.Run(() => Console.WriteLine(_terminator.IWillBeBack()));
    Console.WriteLine("After");
    task.Wait();
}
于 2012-07-31T11:41:30.970 に答える
1

VS 2012 で MS Test フレームワークを使用する場合は、次のようにテストを記述することもできます。

[TestMethod]
public async Task TaskRun()
{
    Console.WriteLine("Before");
    Task t = Task.Run(() => Console.WriteLine(IWillBeBack()));
    Console.WriteLine("After");
    await t;
}

private string IWillBeBack()
{
    Thread.Sleep(3000);
    return "I will be back";
}
于 2012-07-31T11:56:41.410 に答える