【问题标题】:Is the thread blocked when doing database operation?执行数据库操作时线程是否阻塞?
【发布时间】:2015-07-13 14:42:22
【问题描述】:

我们有一个 WCF 服务(部署在 IIS 上),它对数据库进行昂贵的调用。它不使用任何类型的异步 peogramming (async\await)。

using (SqlDataAdapter adapter = new SqlDataAdapter())
{
    using (SqlCommand command = new SqlCommand())
    {
        command.CommandType = CommandType.StoredProcedure;
        command.CommandText = "StoreProcedure_NAME"; //Takes 6 seconds
        command.Connection = connection;
        adapter.SelectCommand = command;
        adapter.Fill(dataset);
        return dataset;
    }
}

现在,在 6 秒的等待时间内调用数据库的线程(我相信这是一个 wcf 线程池线程)会发生什么。该线程是阻塞并占用 CPU 周期还是处于等待状态(等待中断)?

【问题讨论】:

  • 被阻塞的线程不占用CPU周期。

标签: c# multithreading wcf threadpool


【解决方案1】:

是的,它被阻止了。有async 方法旨在将线程返回到侦听池,并在任务完成时从线程池中检索新的(或相同的)线程。非async 方法会阻塞你的调用线程。

【讨论】:

  • 这个线程在被阻塞时是否占用 cpu 周期(当我从这里读到 blog.stephencleary.com/2013/11/there-is-no-thread.html 时,我问这个问题,所有网络调用都是非阻塞的)?我正在使用 ADO.Net 并且 sqladapter 没有公开异步方法,是否有任何优势(我知道它释放了 WCF 线程池线程,但新线程仍然阻塞)我自己创建一个新任务并放置此代码在Task.Run 中?谢谢。
  • @SriHarshaVelicheti 否 - 线程必须在做工作才能在 CPU 上进行调度,从而占用周期。这些线程有效地进入等待状态......直到被告知要恢复长调用的结果,才被调度和空闲(但阻塞)。而不是Task.Run,您应该利用async 方法和回调。
  • 对不起,如果我的问题很幼稚(我试图对多线程有很好的理解),如果我使用异步方法,BCL 不会在内部创建一个新线程来完成数据库调用并被阻塞等待中断?
  • @SriHarshaVelicheti 异步/BCL 的优势在于它们使用 IO 完成线程,低级操作系统线程来执行“阻塞”工作。它们将调用线程返回到线程池以供其他人使用,然后当 IOCP 完成时,从线程池中调用相同(或不同)线程以继续执行您的代码并返回结果。
【解决方案2】:

此线程是否阻塞并占用 CPU 周期或将线程在 等待状态(等待中断)?

它正在等待中断并且不消耗任何 CPU 周期。当您发出 IO 请求时,请求会一直传递到相关的设备驱动程序(或您的情况下的数据库进程),这本质上是异步的。这些 IO 请求通常是注册一个 IRP(IO 请求包)。在数据库情况下,线程将阻塞并等待中断才能恢复。

SqlAdapter 只是使用SqlDataReader 的包装器(至少它是同步API),它在内部确实使用Task Asynchronous Pattern 公开了诸如ReadAsyncNextResultAsync 之类的异步方法。不要不必要地启动新线程,而是使用这些 API。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    • 2013-07-05
    • 2011-03-27
    • 1970-01-01
    相关资源
    最近更新 更多