我们有一个 WCF 服务(部署在 IIS 上),它对数据库进行昂贵的调用。它不使用任何类型的异步编程(async/await)。
using (SqlDataAdapter adapter = new SqlDataAdapter())
{
using (SqlCommand command = new SqlCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "StoredProcedure_NAME"; // takes 6 seconds
command.Connection = connection;
adapter.SelectCommand = command;
adapter.Fill(dataset);
return dataset;
}
}
现在,在 6 秒的等待时间内对数据库进行调用的线程(我相信这是一个 WCF 线程池线程)会发生什么。该线程是否阻塞并占用 CPU 周期,或者线程是否处于等待状态(等待中断)?
是的,被屏蔽了。有
async
方法旨在将线程返回到侦听池,并在任务完成时从线程池中检索新的(或相同的)线程。非 async
方法将阻塞您的调用线程。
该线程是否阻塞并占用 CPU 周期或者线程将处于 等待状态(等待中断)?
它正在等待中断并且不消耗任何CPU周期。当您发出 IO 请求时,请求会一直传递到相关的设备驱动程序(或您的情况下的数据库进程),这本质上是异步的。这些IO请求通常会注册一个IRP(IO请求包)。在数据库情况下,线程将阻塞并等待中断才能恢复。
SqlAdapter
只是使用 SqlDataReader
的包装器(至少是同步 API),它在内部公开了使用 ReadAsync
的异步方法,例如
NextResultAsync
和
Task Asynchronous Pattern
。使用这些 API,而不是不必要地启动新线程。