【发布时间】:2013-05-07 17:32:07
【问题描述】:
我有一个调度程序,它在 ASP.NET 站点的应用程序启动时作为后台线程运行。用户可以启动插入到数据库表中的各种任务(警报电子邮件/文件生成等)。调度程序将从数据库中选择任务并将项目推送到堆栈中。调度程序还有一个线程池,运行 10 个后台线程,这些线程将从堆栈中弹出任务项并执行它。
这在一台网络服务器上运行良好,但在另一台网络服务器上表现异常。即使堆栈中有项目,线程也会无缘无故地空闲 6-12 秒,并且什么也不做。
- 在堆栈对象上使用 lock() 使 Push & Pop 线程安全
- 尝试 Thread.Yield() 让 cpu 让出以执行其他线程,但仍然会减慢执行速度并保持空闲状态
- 尝试 Thread.Sleep(0) 让 cpu 让出以执行其他线程,但仍然会减慢执行速度并保持空闲状态
- 记录所有方法的进入和退出,以检查执行过程中是否出现问题,但没有运气
我的问题:
- .net 中线程的执行是否具有不确定性?
- 是否需要指定 Thread.Yield() 或 Thread.Sleep(0) 给 cpu 呼吸时间?
- 为什么它在具有相同配置的盒子上表现不同?是否有任何特定于机器/环境的因素会影响线程的执行?
2013 年 5 月 8 日更新
农场中有两个盒子,硬件配置相同,软件配置相同,Windows 2008 64bit / IIS7。两个网络服务器只有一个站点,每个站点都具有相同的构建。两个站点的应用程序池在 Framework V4.0 上以集成模式运行。这是一个遗留代码,自过去两年以来没有机会。
我们尝试了几次迭代,在所有情况下,webserver1 都可以正常执行,并像之前一样快速完成后台工作。 但是 webserver2 有很大的延迟并且性能很差。
我们尝试了广泛的日志记录,捕获所有方法的条目/退出。场景是这样的,所有线程正常工作 2 秒,然后空闲 6-12 秒,再次变为活动并执行接下来的 2 秒,然后再次空闲。这种行为一直持续到任务完成。没有异常,没有应用程序终止,应用程序池/iis日志中没有错误。
有什么想法吗?
【问题讨论】:
-
1.是的。 2. 没有。 3. 你可能有一个错误/竞争条件,只有一种配置能够带来;如果不了解更多关于代码的信息,这很难确定。
-
因为这两种方法都在告诉线程在一段时间内什么都不做,明显的结果是吞吐量降低。
-
您在问一个只有调试器才能可靠回答的问题。调试 + 全部中断,调试 + Windows + 线程。查看他们的调用堆栈,看看他们在做什么。
-
@eka 当然,很多。它将确定哪些线程在什么时间被安排在哪些内核上,它们运行多长时间,它们运行的速度,有多少能够同时运行,花多少时间进行生产性工作与上下文切换,然后有是关于如何基于缓存等访问共享内存的各种问题。这只是初学者。
-
@eka 正在运行的任务是否有可能争用共享资源? (也许其中一个任务是长时间运行的并且持有共享资源的锁)
标签: c# .net multithreading parallel-processing clr