LoginSignup
6
4

More than 5 years have passed since last update.

await Task.Delay() は Thread.Sleep() よりレスポンスが悪い

Posted at

注意:ただし場合による。(追記を参照)

以下本文


とは言っても普通の用途で await Task.Delay() を使用していて困ることはないと思います。

結論から言いますと、15ms以下の短い時間を待機したい場合は、 Thread.Sleep() を使用したほうが良いと思います。(ただし、無闇にこの2つを組み合わせ無い方がいいかも?)

私の環境では await Task.Delay(1) から処理が返ってくるのに 15ms くらい掛かったのに対し、 Thread.Sleep(1) ではほぼ 1ms で処理が返ってきました。await は、タスク作成のオーバーヘッドが少ない、後続のプログラムを元と同じスレッドで実行するのが容易などのメリットがありますが、その代わりに応答性が悪くなってしまうようです。もしかしたら環境によっても異なるかもしれません。もっとも、C#を使うべきでない、というのもあるかもしれませんが。

以下のコードは、スレッドを1ms待機させるプログラムを、これらの2つの方法で書いたものです。await Task.Delay() の方が若干時間が掛かっていることがわかります。

環境は Windows 7 SP1, CPU は Core 2 Quad Q9650, .Net Framework 4.5 です。

C#
int delayms = 1;  // ミリ秒

Task.Run(async () =>
{
    int n;
    System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
    s.Start();

    for (n = 0; s.ElapsedMilliseconds < 3000; n++ )
    {
        Thread.Sleep(delayms);
    }

    s.Stop();

    Console.WriteLine("Thread.Sleep(" + delayms + ") の場合");
    Console.WriteLine("  count: " + n + ", interval: " + s.ElapsedMilliseconds / (double)n + "ms");

    s.Restart();

    for (n = 0; s.ElapsedMilliseconds < 3000; n++)
    {
        await Task.Delay(delayms);
    }

    s.Stop();

    Console.WriteLine("await Task.Delay(" + delayms + ") の場合");
    Console.WriteLine("  count: " + n + ", interval: " + s.ElapsedMilliseconds / (double)n + "ms");
}).Wait();
Windows7 (.NET) での実行結果(1)
Thread.Sleep(1) の場合
  count: 2999, interval: 1.00033344448149ms
await Task.Delay(1) の場合
  count: 193, interval: 15.6010362694301ms
Windows7 (.NET) での実行結果(2)
Thread.Sleep(50) の場合
  count: 60, interval: 50.0166666666667ms
await Task.Delay(50) の場合
  count: 49, interval: 62.1632653061224ms

追記

完全に環境によるようです・・・。

rextester.com (.NET 4.0) での実行結果(1)
Thread.Sleep(1) の場合
  count: 193, interval: 15.6010362694301ms
await Task.Delay(1) の場合
  count: 193, interval: 15.5958549222798ms
rextester.com (.NET 4.0) での実行結果(2)
Thread.Sleep(15) の場合
  count: 191, interval: 15.7853403141361ms
await Task.Delay(15) の場合
  count: 161, interval: 18.6894409937888ms

こちらでは逆転してawaitの方が高速でした・・・。

ideone.com (Mono) での実行結果(1)
Success time: 3.06 memory: 30512 signal:0
Thread.Sleep(1) の場合
  count: 1498, interval: 2.00333778371162ms
await Task.Delay(1) の場合
  count: 2920, interval: 1.02739726027397ms
ideone.com (Mono) での実行結果(2)
Success time: 0.11 memory: 30512 signal:0
Thread.Sleep(15) の場合
  count: 188, interval: 16.0212765957447ms
await Task.Delay(15) の場合
  count: 199, interval: 15.1306532663317ms
6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4