【发布时间】:2012-07-16 21:47:55
【问题描述】:
我做了一个简单的异步方法来异步调用 SQL 存储过程。
在我的控制台程序中,我在循环中调用此方法 1000 次,并在每次调用之间休眠 1ms (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 的回答。
【问题讨论】:
-
您在这两种情况下都在运行控制台程序?
-
尝试在调试器中中断几次,看看它在您的服务器计算机上停止的位置。
-
部分异步方法仍然同步运行(尤其是 DNS 查找)。
-
@usr :在没有附加调试器的情况下,我确实在运行相同的控制台程序(在 Release 中编译)。不幸的是,服务器机器没有配置为允许远程调试,如果没有人知道,我会在万不得已的情况下这样做;)
-
@SLaks :确实,但这不是这里的问题。问题是,在我的桌面开发机器上,该方法是完全异步运行的,而在服务器机器上,该方法是同步(或部分异步)运行的。
标签: c# .net async-await