2016-08-12 71 views
2

我们看到很多像以下这样的调用堆栈,我可以知道什么是条件\情况会发生吗?看到很多clr!CLRSemaphore ::在调用堆栈中等待

OS Thread Id: 0x48654 (559) 
Current frame: ntdll!NtWaitForSingleObject+0xa 
Child-SP   RetAddr   Caller, Callee 
00000020a76cf480 00007fffd4ea1118 KERNELBASE!WaitForSingleObjectEx+0x94, calling ntdll!NtWaitForSingleObject 
00000020a76cf520 00007fffce50ce66 clr!CLRSemaphore::Wait+0x8a, calling kernel32!WaitForSingleObjectEx 
00000020a76cf5e0 00007fffce50d247 clr!ThreadpoolMgr::UnfairSemaphore::Wait+0x109, calling clr!CLRSemaphore::Wait 
00000020a76cf620 00007fffce50d330 clr!ThreadpoolMgr::WorkerThreadStart+0x1b9, calling clr!ThreadpoolMgr::UnfairSemaphore::Wait 
00000020a76cf6c0 00007fffce5de8b6 clr!Thread::intermediateThreadProc+0x7d 
00000020a76cfb40 00007fffce5de89f clr!Thread::intermediateThreadProc+0x66, calling clr!_chkstk 
00000020a76cfb80 00007fffd60613d2 kernel32!BaseThreadInitThunk+0x22 
00000020a76cfbb0 00007fffd7be5454 ntdll!RtlUserThreadStart+0x34 
OS Thread Id: 0x3bd4c (560) 
Current frame: ntdll!NtWaitForSingleObject+0xa 
Child-SP   RetAddr   Caller, Callee 
00000020a774e910 00007fffd4ea1118 KERNELBASE!WaitForSingleObjectEx+0x94, calling ntdll!NtWaitForSingleObject 
00000020a774e9b0 00007fffce50ce66 clr!CLRSemaphore::Wait+0x8a, calling kernel32!WaitForSingleObjectEx 
00000020a774ea70 00007fffce50d247 clr!ThreadpoolMgr::UnfairSemaphore::Wait+0x109, calling clr!CLRSemaphore::Wait 
00000020a774eab0 00007fffce50d330 clr!ThreadpoolMgr::WorkerThreadStart+0x1b9, calling clr!ThreadpoolMgr::UnfairSemaphore::Wait 
00000020a774eb50 00007fffce5de8b6 clr!Thread::intermediateThreadProc+0x7d 
00000020a774ec30 00007fffd7c00c75 ntdll!RtlpLowFragHeapAllocFromContext+0x355, calling ntdll!memset 
+0

0:030>做0000001fc0a80fe8 名称:System.Runtime.Remoting .Contexts.Context MethodTable:00007fffcd2ae6c8 EEClass:00007fffccd74ad8 Size:104(0x68)bytes File:C:\ Windows \ Microsoft.Net \ assembly \ GAC_64 \ mscorlib \ v4.0_4.0.0.0__b77a5c5619 BTW,我们也看到线程上下文是System.Runtime.Remoting.Contexts.Context – Jason

+0

只是基于调用堆栈中的函数名称,看起来像一个空闲的工作线程 - 一个等待工作到达。 –

+0

这是一个线程池线程完全正常的状态,它正在等待工作要做。如果你看到它们中的很多,那么之前出现了一些错误,你有太多的线程池请求需要花费很长时间才能完成。活动TP线程数的上限非常高。除了更好地平衡工作负载之外,理想的解决方案当然也是调用ThreadPool.SetMaxThreads()。 –

回答

5

如已经评论提及@Harry Johnston,这些都是无关的线程池的工作线程。

以下示例可用于复制此类堆栈。它会创建12个线程池工作线程,当调试器中断时,它们都处于闲置状态,就像您看到的一样。

的代码是基于微软的Fibunacci threadpool example

using System.Diagnostics; 
using System.Threading; 

public class Fibonacci 
{ 
    public void ThreadPoolCallback(object threadContext) 
    { 
     FibOfN = Calculate(N); 
     DoneEvent.Set(); 
    } 

    public int Calculate(int n) 
    { 
     if (n <= 1) return n; 
     return Calculate(n - 1) + Calculate(n - 2); 
    } 

    public int N { get; set; } 
    public int FibOfN { get; private set; } 
    public ManualResetEvent DoneEvent { get; set; } 
} 

public class ClrSemaphoreWaitDemo 
{ 
    static void Main() 
    { 
     const int numberOfTasks = 12; 
     var doneEvents = new ManualResetEvent[numberOfTasks]; 
     var fibArray = new Fibonacci[numberOfTasks]; 
     ThreadPool.SetMaxThreads(numberOfTasks, numberOfTasks); 
     ThreadPool.SetMinThreads(numberOfTasks, numberOfTasks); 

     for (int i = 0; i < numberOfTasks; i++) 
     { 
      doneEvents[i] = new ManualResetEvent(false); 
      fibArray[i] = new Fibonacci {N= 4, DoneEvent= doneEvents[i]}; 
      ThreadPool.QueueUserWorkItem(fibArray[i].ThreadPoolCallback, i); 
     } 

     WaitHandle.WaitAll(doneEvents); 
     Debug.WriteLine("Now run .symfix; .reload; .loadby sos clr; !threads; !threads; !findstack clr!CLRSemaphore::Wait"); 
     Debugger.Break(); 
    } 
} 

当中断调试,运行以下命令:

.symfix; .reload; .loadby sos clr; !threads; !threads; !findstack clr!CLRSemaphore::Wait 
+0

您好托马斯,非常感谢您对我的多个主题的热情帮助,我会一一检查,然后给出回复。再次感谢您的支持。 – Jason

+1

Thomas,这意味着在线程池线程完成工作之后,在它死亡\被销毁之前,它们会调用clr!CLRSemaphore ::等待查看是否还有更多工作要做,并且如果它们保持该状态并在20秒左右没有更多的工作要做,他们会死亡\被摧毁,对吧? – Jason

+1

基本上是的,他们通过一个信号量等待新作品的到来,这个信号量将在新作品到达时设定。在这种状态下,您无法分辨他们是否成功完成工作或发生了什么问题(例如发生异常)。关于20秒:我实际上不知道他们是否会在一段时间后被销毁。通过在调试器中断之前添加一个Sleep()调用,您可以轻松地使用上面的代码尝试。 –