为什么C#线程在执行期间处于空闲状态?

为什么C#线程在执行期间处于空闲状态?,c#,.net,multithreading,parallel-processing,clr,C#,.net,Multithreading,Parallel Processing,Clr,我有一个调度程序,它在ASP.NET站点的应用程序启动时作为后台线程运行。用户可以启动插入db表中的各种任务(警报电子邮件/文件生成等)。调度程序将从数据库中拾取任务,并将这些项推送到堆栈中。调度器还有一个运行10个后台线程的线程池,它将从堆栈中弹出任务项并执行它 这在一个web服务器上运行正常,但在另一个web服务器上表现异常。线程会无缘无故地空闲6-12秒,即使堆栈中有项目,也不会执行任何操作 在堆栈对象上使用lock()使Push&Pop线程安全 已尝试Thread.Yield()使cp

我有一个调度程序,它在ASP.NET站点的应用程序启动时作为后台线程运行。用户可以启动插入db表中的各种任务(警报电子邮件/文件生成等)。调度程序将从数据库中拾取任务,并将这些项推送到堆栈中。调度器还有一个运行10个后台线程的线程池,它将从堆栈中弹出任务项并执行它

这在一个web服务器上运行正常,但在另一个web服务器上表现异常。线程会无缘无故地空闲6-12秒,即使堆栈中有项目,也不会执行任何操作

  • 在堆栈对象上使用lock()使Push&Pop线程安全
  • 已尝试Thread.Yield()使cpu能够执行其他线程,但仍然会降低执行速度并使其处于空闲状态
  • 已尝试Thread.Sleep(0)让cpu执行其他线程,但仍然会降低执行速度并使其空闲
  • 记录所有方法的入口和出口,以检查执行过程中是否出现问题,但没有运气
我的问题是:

  • net中线程的执行是确定性的吗
  • 是否需要指定Thread.Yield()或Thread.Sleep(0)为cpu提供呼吸时间
  • 为什么它在具有相同配置的盒子上表现不同?是否有任何特定于机器/环境的因素会影响线程的执行
  • 更新日期:2013年5月8日

    场中有两个框,两个框的硬件配置相同,使用相同的软件配置以及Windows 2008 64位/IIS7进行设置。两个Web服务器只有一个站点,每个站点具有相同的构建。两个站点的应用程序池都在集成模式下的Framework V4.0上运行。这是一个遗留代码,自过去两年以来没有机会

    我们尝试了几次迭代,在所有情况下,webserver1都可以毫无问题地执行,并像以前一样快速完成后台工作但是webserver2有很大的延迟,性能非常差。

    我们尝试了大量的日志记录,捕获所有方法的入口/出口。场景是这样的,所有线程正常工作2秒,然后空闲6-12秒,再次变为活动并在接下来的2秒执行,然后再次空闲。这种行为在任务完成之前是一致的。应用程序池/iis日志中没有异常、应用程序终止和错误


    有什么想法吗?

    您的线程反复尝试获取锁,这可能会导致争用。但不应该是6-12秒-只有调试器才能提供答案


    您可以使用
    AutoResetEvent
    并在工作线程中等待它,并且
    Set
    在将项推送到堆栈时设置事件

    好了,伙计们,我们终于解决了这个问题

    Web服务器的一个cpu核心达到了100%,再也没有恢复。而其他岩芯含量为0-5%

    我们对正常-中等-重型负载进行了负载测试。在生成正常到中等负载的同时,服务器正在以适当的方式提供服务,与所有其他cpu核心正确地共享进程执行。但当我们产生重负载时,情况会发生变化,服务器会努力在内核之间分配负载,线程会闲置6-7秒。我们假设,由于一个cpu内核出现故障,它将处理一些模糊逻辑,以便在内核之间分配进程


    经过进一步调查,我们发现Windows NT内核导致此问题,可能是由于损坏或驱动程序相关问题。

    1。对2.三号。您可能有一个bug/race条件,只有一个配置能够带来;如果不了解更多的代码,就很难确定这一点。因为这两种方法都在告诉线程在一段时间内不执行任何操作,明显的结果是吞吐量较低。您提出的问题只有调试器才能可靠地回答。调试+全部中断,调试+窗口+线程。看看他们的呼叫堆栈,看看他们在做什么。@eka当然,很多。它将确定哪些线程在什么时间调度在哪些内核上,运行时间有多长,运行速度有多快,有多少线程能够同时运行,花多少时间做生产性工作,而不是在上下文切换上,然后在如何基于缓存访问共享内存方面存在各种各样的问题,等等,这只是开始。@eka是否有可能运行的任务正在争夺共享资源?(可能其中一个任务是长时间运行的,并且持有对共享资源的锁)不,我不这么认为,我们记录了方法的入口和出口,并且lock语句在方法调用中。his甚至不支持这种方法。如果只有两个线程,我还可以使用autoreset事件通知对方。在我的例子中,有多个线程(10)监视堆栈。我无法调用reset来通知特定的线程抱歉,我没有理解“his甚至没有提交到该方法”的含义。如果使用发行版生成二进制文件,则不会打印调试写入语句。改用
    跟踪
    。所有10个线程都可以在一个AutoResetEvent上等待。当您将一个项目推送到堆栈时,调用
    Set
    。其中一个等待线程将被释放并处理该项。根据对问题本身的一些评论和@sgorozco的一条评论,无需调用
    Reset
    ——如果模拟代码工作正常,我们就不可能解决您的问题。你必须透露更多细节。线程可以冻结的一种可能性是垃圾收集。检查是否在启动时通过创建太多对象无意中导致GC。对您来说,最好的解决方案是,若您有$$$,那个么就通过探查器运行代码。或者,当您看到延迟时,也可以对流程进行挂起转储,然后检查heapstats。好的-看起来我们在讨论中缺少了一些基本的东西。因为您的系统是生产m