SQLストアドプロシージャを非同期で呼び出すための単純な非同期メソッドを作成しました。
私のコンソールプログラムでは、このメソッドをループで1000回呼び出しており、各呼び出しの間に1ms(Thread.Sleep)スリープします。ループに入る前にストップウォッチを開始し、ループを終了するときにストップウォッチを停止して、ループに費やされた時間を表示します。
私の開発マシン(Win7-VS 2012 RC)で、私が期待していたものを見ることができます:
Completed in 1006 ms
asyncメソッドの呼び出しが(最初のawait
キーワードに到達すると)ほぼ即座に返されることを考えると、これは論理的であるように思われます。したがって、待機する前にコードを実行する際に発生するオーバーヘッド(6ms)はわずかです。
ただし、.NET Framework 4.5 RCをインストールしたサーバーマシン(Win2008 R2 SP1)でまったく同じコードを実行すると、コードは正常に実行されますが、実行時間は期待したものとは異なり、私の開発マシンでプログラムを実行したときに取得したもの:
Completed in 15520 ms
どういうわけか、呼び出されている非同期メソッドは実際には非同期的に呼び出されておらず、最初の待機はどういうわけかブロックされているように見えるという意味ですか?
これが私が呼んでいる非同期メソッドのコードです:
public async void CallSpAsync()
{
var cmd = new SqlCommand("sp_mysp");
{
var conn = new SqlConnection(connectionString);
{
cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
[...Filling command parameters here - nothing interesting...]
await cmd.Connection.OpenAsync();
await cmd.ExecuteNonQueryAsync();
cmd.Dispose();
cmd.Connection.Dispose();
}
}
}
そしてここにメインプログラムのテストコード(ループ)があります:
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
CallSpAsync();
Thread.Sleep(1);
}
sw.Stop();
両方のマシンでまったく同じ実行可能ファイル(リリースでコンパイルされたコンソールプログラム)を実行しています。
サーバーマシンでプログラムを実行しているときに、メソッドが本当に非同期で呼び出されない理由を理解するのに苦労しています。
何か案が ?
ありがとう !
編集
この問題は、正常に機能しているasync / awaitとは何の関係もありませんが、サーバーのタイマー解像度(StopWatchで使用)がワークステーションの15分の1であることが原因です。コードの実行速度はまったく遅くなりません。経過時間の計算が正しくない原因となっているのは、タイマーの解像度だけです。
以下のJamesManningからの回答を参照してください。