5

我做了一个简单的异步方法来异步调用 SQL 存储过程。

在我的控制台程序中,我在循环中调用此方法 1000 次,并在每次调用之间休眠 1 毫秒(Thread.Sleep)。我在进入循环之前启动一个秒表,并在退出循环时停止它,并显示在循环中花费的时间。

在我的开发机器(Win7 - VS 2012 RC)上,我可以看到我期望看到的内容:

Completed in 1006 ms

这似乎是合乎逻辑的,考虑到对 async 方法的调用几乎立即返回(当到达第一个await关键字时),因此在等待之前执行代码时只会产生很小的开销(6 毫秒)。

但是,当我在安装了 .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();

我在两台机器上运行完全相同的可执行文件(在 Release 中编译的控制台程序)。

我很想弄清楚为什么在服务器机器上运行程序时没有真正异步调用该方法。

任何的想法 ?

谢谢 !

编辑

该问题与运行正常的 async/await 无关,但由于服务器上的计时器分辨率(由 StopWatch 使用)比我的工作站上的时间少 15 倍。代码根本没有运行得更慢,只是计时器的分辨率导致了不正确的经过时间计算。

请参阅下面 James Manning 的回答。

4

1 回答 1

3

这可能是服务器机器上计时器分辨率的函数。检查 ClockRes 实用程序。您可以在我对高精度 DateTime.UtcNow的评论中获得更多详细信息。

于 2012-07-16T22:44:05.943 回答