Finding out the Thread which is actually handling the WCF request for the HttpContext

In the recent past, the PSSCOR2 debugger extension was made public. This debugger extension contains a very useful command called !aspxpages which shows you information about various asp.net requests running in the dump, the time they have been executing and the thread associated with the System.Web.HttpContext. Here is an example of what this command shows you

 

 0:000> !aspxpages
Going to dump the HttpContexts found in the heap.
Loading the heap objects into our cache.
HttpContext    Timeout  Completed     Running  ThreadId ReturnCode   Verb RequestPath+QueryString
0x01bbf914    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bc0ba4    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bc17c4    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bc4660    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bc56a4    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bc6660    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bc76a4    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bc8660    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bc96a4    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bca6fc    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bcb740    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bcc6fc    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bcd740    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bce6fc    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bcf740    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bd0784    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bd17c8    11647 Sec        no        29 Sec      27        200   POST /MySleepingWcfService/Service.svc 
0x01bd2814    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bd3858    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01bd4814    11647 Sec        no        29 Sec      29        200   POST /MySleepingWcfService/Service.svc 
0x01bd68dc    11647 Sec        no        29 Sec      24        200   POST /MySleepingWcfService/Service.svc 
0x01bdb404    11647 Sec        no        29 Sec      31        200   POST /MySleepingWcfService/Service.svc 
0x01be3404    11647 Sec        no        28 Sec      33        200   POST /MySleepingWcfService/Service.svc 
0x01bfd404    11647 Sec        no        28 Sec      35        200   POST /MySleepingWcfService/Service.svc 
0x01c0f41c    11647 Sec        no        27 Sec      37        200   POST /MySleepingWcfService/Service.svc 
0x01c1541c    11647 Sec        no        27 Sec      39        200   POST /MySleepingWcfService/Service.svc 
0x01c3c634    11647 Sec       yes                   XXX        200   POST /MySleepingWcfService/Service.svc 
0x01c404c8    11647 Sec        no        25 Sec      41        200   POST /MySleepingWcfService/Service.svc 
0x01c6264c    11647 Sec        no        25 Sec      44        200   POST /MySleepingWcfService/Service.svc 
Total 29 HttpContext objects
    

Using this information you can find out the thread which is handling your request and if the request is taking a longer time to execute, you can check the callstack of the thread to see what it is doing and why it is taking a longer time to execute and this is pretty helpful. If you are hosting WCF services inside IIS, the same command will show you the information about the HttpContexts associated with the WCF requests and the thread handing the request but because of the way the WCF requests work inside IIS, the thread reported by the !aspxpages command will always show you the call-stack like below.

 0:027> !clrstack
OS Thread Id: 0x2740 (27)
ESP       EIP     
0f4af060 775564f4 [HelperMethodFrame_1OBJ: 0f4af060] System.Threading.WaitHandle.WaitOneNative(Microsoft.Win32.SafeHandles.SafeWaitHandle, UInt32, Boolean, Boolean) 
0f4af10c 6f6e685f System.Threading.WaitHandle.WaitOne(Int64, Boolean) 
0f4af128 6f6e6815 System.Threading.WaitHandle.WaitOne(Int32, Boolean) 
0f4af13c 6f6e67dd System.Threading.WaitHandle.WaitOne() 
0f4af144 79962000 System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(System.Web.HttpApplication, Boolean)
0f4af174 799618f4 System.ServiceModel.Activation.HttpModule.ProcessRequest(System.Object, System.EventArgs)
0f4af19c 6574ec35 System.Web.HttpApplication+SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 
0f4af1b4 65742a5c System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef) 
0f4af1f4 6574e1f3 System.Web.HttpApplication+ApplicationStepManager.ResumeSteps(System.Exception) 
0f4af244 65741fdc System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext, System.AsyncCallback, System.Object) 
0f4af260 6574554c System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest) 
0f4af294 657451f3 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest) 
0f4af2a4 6574438c System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32) 
0f4af4b8 70290256 [ContextTransitionFrame: 0f4af4b8]  
0f4af4ec 70290256 [GCFrame: 0f4af4ec]  
0f4af648 70290256 [ComMethodFrame: 0f4af648] 

The reason for this is the way WCF runtime handles the request. You will always see two threads to process the WCF request. One thread is the CLR ThreadPool thread (which will look something like the above thread) which is the worker thread that comes from ASP.NET and the other thread is an I/O thread that is managed by the WCF IOThreadScheduler (actually created by ThreadPool.UnsafeQueueNativeOverlapped). More details on this behavior are mentioned in this blog.

Most of the times you are interested in finding out the actual WCF thread which is servicing this request because that would be the thread which is actually executing the method code inside your WCF service and if your service it service method is taking a long time to execute, that would be thread that would be the thread that requires attention.

Read full post here - https://blogs.msdn.microsoft.com/puneetgupta/2011/01/11/finding-out-the-thread-which-is-actually-handling-the-wcf-request-for-the-httpcontext/