一个WCF请求由两个线程来完成

运行在IIS上的WCF service, 你可能会注意到一个比较有趣的现象. 当WCF service接收到一个请求时, 这个请求实际上会有两个线程在执行这个请求.

  • 一个线程是来自于CLR的ThreadPool的线程. 这是一个Worker Thread用于接收.svc页面的访问请求.
  • 另外一个线程是 I/O 线程, 用于执行WCF的逻辑.

你可以参考下面的实例代码. 该代码用于模拟一个WCF执行时间比较长的场景.

[ServiceContract]
public interface IService1
{
    [OperationContract]
    string GetData(int value);
}

public class Service1 : IService1
{
    public string GetData(int value)
    {
        System.Threading.Thread.Sleep(value * 1000);

return string.Format("You slept : {0} seconds", value);
    }

}

如果是.NET Framework 3.5, 您会在运行时看到类似的CALL STACK. 线程26 正在执行一个Service1.svc的请求. 整个请求正是一个WCF的请求. 从CALL STACK上看, 这个线程已经被挂起, 并且等待一个异步线程的返回.

通过!threads命令, 可以验证这个线程是一个Worker Thread. 在这一点上, .svc页面的请求与.aspx页面的请求, 并没有太多的区别.

0:026> !psscor2.aspxpages
Going to dump the HttpContexts found in the heap.
HttpContext    Timeout  Completed     Running  ThreadId ReturnCode   Verb RequestPath+QueryString
0x00000006101094a0    110Sec        no         3 Sec      26        200   POST /Service1.svc
Total 5 HttpContext objects

0:026> !clrstack
OS Thread Id: 0x12a0 (26)
Child-SP         RetAddr          Call Site
00000006931be540 00007ff97510422b System.Threading.WaitHandle.WaitOne(Int64, Boolean)
00000006931be580 00007ff975100c6c System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(System.Web.HttpApplication, Boolean)
00000006931be610 00007ff9bd458b90 System.ServiceModel.Activation.HttpModule.ProcessRequest(System.Object, System.EventArgs)
00000006931be660 00007ff9bd4497db System.Web.HttpApplication+SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
00000006931be6c0 00007ff9bdb3ffa1 System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef)
00000006931be760 00007ff9bdb304f2 System.Web.HttpApplication+PipelineStepManager.ResumeSteps(System.Exception)
00000006931be8f0 00007ff9bdb11e79 System.Web.HttpApplication.BeginProcessRequestNotification(System.Web.HttpContext, System.AsyncCallback)
00000006931be940 00007ff9bdc42f61 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest, System.Web.HttpContext)
00000006931bea60 00007ff9bdc42b2b System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)
00000006931bebe0 00007ff9bdc42884 System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
00000006931bec40 00007ff9d48f8b9a DomainNeutralILStubClass.IL_STUB(Int64, Int64, Int64, Int32)
00000006931bf4a0 00007ff9bdc43090 DomainNeutralILStubClass.IL_STUB(IntPtr, System.Web.RequestNotificationStatus ByRef)
00000006931bf580 00007ff9bdc42b2b System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)
00000006931bf700 00007ff9bdc42884 System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
00000006931bf760 00007ff9d48f8deb DomainNeutralILStubClass.IL_STUB(Int64, Int64, Int64, Int32)

0:029> !threads
ThreadCount: 9
UnstartedThread: 0
BackgroundThread: 9
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
                                              PreEmptive                                                Lock
       ID OSID        ThreadOBJ     State   GC     GC Alloc Context                  Domain           Count APT Exception
   7    1 1d00 000000054eb974b0      8220 Enabled  0000000550122328:0000000550123008 000000054eb8f200     0 Ukn
  22    2 5dcc 000000054eba9620      b220 Enabled  0000000000000000:0000000000000000 000000054eb8f200     0 MTA (Finalizer)
  24    3 4234 00000006914a4f00    80a220 Enabled  0000000000000000:0000000000000000 000000054eb8f200     0 MTA (Threadpool Completion Port)
  25    4 500c 00000006914a6560      1220 Enabled  0000000000000000:0000000000000000 000000054eb8f200     0 Ukn
  26    5 12a0 000000069151ee20   380b220 Enabled  000000061010a9e8:000000061010afd0 00000006914a7010     1 MTA (Threadpool Worker)

这个请求正是  I/O 线程来执行, 从Managed的Call Stack上可以看出来是执行了上面实例代码的Service1.GetData的方法.

在Native的Callstack中, mscorwks!ThreadpoolMgr::CompletionPortThreadStart 说明了这里开始的是一个I/O线程. 通过 !thread 命令, 同样也可以验证出这个是I/O线程.

0:029> !clrstack
OS Thread Id: 0x5894 (29)
Child-SP         RetAddr          Call Site
00000006941ce740 00007ff97570022c WCFSite.Service1.GetData(Int32)
00000006941ce790 00007ff975751329 DynamicClass.SyncInvokeGetData(System.Object, System.Object[], System.Object[])
00000006941ce7d0 00007ff9754ab99c System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(System.Object, System.Object[], System.Object[] ByRef)
00000006941ce920 00007ff9754ab092 System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(System.ServiceModel.Dispatcher.MessageRpc ByRef)
00000006941ce9f0 00007ff9754aac57 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(System.ServiceModel.Dispatcher.MessageRpc ByRef)
00000006941cea80 00007ff9754a91b3 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(System.ServiceModel.Dispatcher.MessageRpc ByRef)
00000006941ceb00 00007ff9754a82e3 System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean)
00000006941cebc0 00007ff9754a588f System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(System.ServiceModel.Channels.RequestContext, Boolean, System.ServiceModel.OperationContext)
00000006941cef10 00007ff9754a51d7 System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(System.ServiceModel.Channels.RequestContext, System.ServiceModel.OperationContext)
00000006941cef80 00007ff975105bad System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(System.IAsyncResult)
00000006941cefd0 00007ff9d3849789 System.ServiceModel.Channels.IOThreadScheduler+CriticalHelper+WorkItem.Invoke2()
00000006941cf050 00007ff975105b30 System.Security.SecurityContext.Run(System.Security.SecurityContext, System.Threading.ContextCallback, System.Object)
00000006941cf090 00007ff975105a0c System.ServiceModel.Channels.IOThreadScheduler+CriticalHelper+WorkItem.Invoke()
00000006941cf0e0 00007ff975105842 System.ServiceModel.Channels.IOThreadScheduler+CriticalHelper.ProcessCallbacks()
00000006941cf150 00007ff9751057b1 System.ServiceModel.Channels.IOThreadScheduler+CriticalHelper.CompletionCallback(System.Object)
00000006941cf190 00007ff975105705 System.ServiceModel.Channels.IOThreadScheduler+CriticalHelper+ScheduledOverlapped.IOCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
00000006941cf1c0 00007ff9d381a85e System.ServiceModel.Diagnostics.Utility+IOCompletionThunk.UnhandledExceptionFrame(UInt32, UInt32, System.Threading.NativeOverlapped*)
00000006941cf220 00007ff9d48fb022 System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)

0:029> kL
Child-SP          RetAddr           Call Site
00000006`941ce408 00007ff9`ec76124a ntdll!ZwDelayExecution+0xa
00000006`941ce410 00007ff9`d4b6feed KERNELBASE!SleepEx+0xa2
00000006`941ce4b0 00007ff9`d474a585 mscorwks!EESleepEx+0x2d
00000006`941ce530 00007ff9`d4d2e2d9 mscorwks!Thread::UserSleep+0x71
00000006`941ce590 00007ff9`757101ab mscorwks!ThreadNative::Sleep+0xf9
00000006`941ce740 00007ff9`7570022c WCFSite!WCFSite.Service1.GetData(Int32)+0x3b
00000006`941ce790 00007ff9`75751329 System_ServiceModel!DynamicClass.SyncInvokeGetData(System.Object, System.Object[], System.Object[])+0x5c
00000006`941ce7d0 00007ff9`754ab99c System_ServiceModel!System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(System.Object, System.Object[], System.Object[] ByRef)+0x3a9
00000006`941ce920 00007ff9`754ab092 System_ServiceModel!System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(System.ServiceModel.Dispatcher.MessageRpc ByRef)+0x12c
00000006`941ce9f0 00007ff9`754aac57 System_ServiceModel!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(System.ServiceModel.Dispatcher.MessageRpc ByRef)+0x162
00000006`941cea80 00007ff9`754a91b3 System_ServiceModel!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(System.ServiceModel.Dispatcher.MessageRpc ByRef)+0x77
00000006`941ceb00 00007ff9`754a82e3 System_ServiceModel!System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean)+0x103
00000006`941cebc0 00007ff9`754a588f System_ServiceModel!System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(System.ServiceModel.Channels.RequestContext, Boolean, System.ServiceModel.OperationContext)+0x4f3
00000006`941cef10 00007ff9`754a51d7 System_ServiceModel!System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(System.ServiceModel.Channels.RequestContext, System.ServiceModel.OperationContext)+0x18f
00000006`941cef80 00007ff9`75105bad System_ServiceModel!System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(System.IAsyncResult)+0x47
00000006`941cefd0 00007ff9`d3849789 System_ServiceModel!System.ServiceModel.Channels.IOThreadScheduler+CriticalHelper+WorkItem.Invoke2()+0x3d
00000006`941cf050 00007ff9`75105b30 mscorlib_ni!System.Security.SecurityContext.Run(System.Security.SecurityContext, System.Threading.ContextCallback, System.Object)+0x69
00000006`941cf090 00007ff9`75105a0c System_ServiceModel!System.ServiceModel.Channels.IOThreadScheduler+CriticalHelper+WorkItem.Invoke()+0x50
00000006`941cf0e0 00007ff9`75105842 System_ServiceModel!System.ServiceModel.Channels.IOThreadScheduler+CriticalHelper.ProcessCallbacks()+0x16c
00000006`941cf150 00007ff9`751057b1 System_ServiceModel!System.ServiceModel.Channels.IOThreadScheduler+CriticalHelper.CompletionCallback(System.Object)+0x62
00000006`941cf190 00007ff9`75105705 System_ServiceModel!System.ServiceModel.Channels.IOThreadScheduler+CriticalHelper+ScheduledOverlapped.IOCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)+0x11
00000006`941cf1c0 00007ff9`d381a85e SMDiagnostics!System.ServiceModel.Diagnostics.Utility+IOCompletionThunk.UnhandledExceptionFrame(UInt32, UInt32, System.Threading.NativeOverlapped*)+0x45
00000006`941cf220 00007ff9`d48fb022 mscorlib_ni!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)+0xce
00000006`941cf270 00007ff9`d4797bc3 mscorwks!CallDescrWorker+0x82
00000006`941cf2d0 00007ff9`d4797a82 mscorwks!CallDescrWorkerWithHandler+0xd3
00000006`941cf370 00007ff9`d4760b3b mscorwks!DispatchCallDebuggerWrapper+0x3e
00000006`941cf3d0 00007ff9`d4cc86a3 mscorwks!DispatchCallNoEH+0x5f
00000006`941cf450 00007ff9`d473a768 mscorwks!BindIoCompletionCallBack_Worker+0xb3
00000006`941cf510 00007ff9`d476c2c5 mscorwks!ManagedThreadBase_DispatchInner+0x2c
00000006`941cf560 00007ff9`d48556a1 mscorwks!ManagedThreadBase_DispatchMiddle+0x9d
00000006`941cf630 00007ff9`d472cb89 mscorwks!ManagedThreadBase_DispatchOuter+0x31
00000006`941cf670 00007ff9`d473a405 mscorwks!ManagedThreadBase_DispatchInCorrectAD+0x15
00000006`941cf6a0 00007ff9`d473a78d mscorwks!Thread::DoADCallBack+0x145
00000006`941cf810 00007ff9`d476c2c5 mscorwks!ManagedThreadBase_DispatchInner+0x51
00000006`941cf860 00007ff9`d48556a1 mscorwks!ManagedThreadBase_DispatchMiddle+0x9d
00000006`941cf930 00007ff9`d48b8c11 mscorwks!ManagedThreadBase_DispatchOuter+0x31
00000006`941cf970 00007ff9`d4de135a mscorwks!ManagedThreadBase_FullTransitionWithAD+0x35
00000006`941cf9d0 00007ff9`d4de1533 mscorwks!BindIoCompletionCallbackStubEx+0xca
00000006`941cfa80 00007ff9`d471bc0e mscorwks!BindIoCompletionCallbackStub+0x13
00000006`941cfab0 00007ff9`d4737f74 mscorwks!ThreadpoolMgr::CompletionPortThreadStart+0x186
00000006`941cfb50 00007ff9`eecb16ad mscorwks!Thread::intermediateThreadProc+0x78
00000006`941cfe20 00007ff9`ef294629 kernel32!BaseThreadInitThunk+0xd
00000006`941cfe50 00000000`00000000 ntdll!RtlUserThreadStart+0x1d

0:029> !threads
ThreadCount: 9
UnstartedThread: 0
BackgroundThread: 9
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
                                              PreEmptive                                                Lock
       ID OSID        ThreadOBJ     State   GC     GC Alloc Context                  Domain           Count APT Exception
  29    8 5894 0000000693d8c760   a80b220 Enabled  00000005d031b410:00000005d031cfd0 00000006914a7010     0 MTA (Threadpool Completion Port)

异步请求的执行

非常不同于原先Web Page和Web Servcie的执行方式. Web Page和Web Servcie均由ASP.NET的Worker Thread来执行请求. WCF最为显著的特点即是异步执行.

这一优势体现在 : WCF应用有更高的灵活性. 能够同一时间平行的执行不同的操作请求. 在WCF操作执行完成之后, 将CALLBACK到之前用于handle页面请求的线程上. 并由这个线程(WorkerThread)来进行返回. 从而提供了WCF服务的吞吐量.

传统的Web Page和Web Service, 当终端客户发起一个请求的时候, 总是会期待服务器端返回一个结果. 因此, 如果发起的请求在服务器端遇到了一些瓶颈, 造成长时间的执行. 客户端也必然需要处于等待状态.

在这种WCF的执行模式下, WCF客户端可以运行在Fire And Forget的模式下. 在有些情况下, 客户端只希望向服务器端发送一个执行请求, 但是并不在乎服务器端执行的结果, 因此也没有必要等待服务器端的返回. 只是的将执行请求提交到WCF服务端, 剩下的事情由WCF服务端来完成. 也不希望收到WCF服务端执行时间长短的影响. 如果有这种需要, 可以运行在fire and forget的模式下. 页面请求在Worker Thread接收后, 按照正常的步骤异步调用I/O线程并且执行WCF的操作.于此同时Worker Thread 可以立即返回响应客户端.

请参考 :

What You Need To Know About One-Way Calls, Callbacks, And Events

Need sample fire and forget async call to WCF service

WCF 4.5上的改进

上面已经讨论了很多WCF请求是如何又两个线程来执行的, 以及这种方式的优点. 然而, 这种方式在.NET FRAMEWROK 3.5上依然有一些缺陷.

按照上面的示例. 当请求到达WCF Servcie后, 服务端会启动两个线程. 一个Worker Thread和一个 I/O Completion Port. Worker Thread用于接收.svc页面的请求, 并且等待IOCP的执行完成然后返回到客户端. IOCP则运用WCF的操作. 在代码中, WCF的操作会sleep一段时间, 用于模拟长时间的操作. 在这种情况下, 我们可以看到Work Thread是一直处于等待状态.

这种情况下会产生一个问题. 如果WCF的操作都非常耗时, 而且此时业务非常繁忙. 进程的线程池有可能很快就会耗尽. 而且这些线程看起来无所事事, 绝大多数都在等待WCF操作的返回而已. 这显然造成了一种浪费. 在提高异步执行能力的同时, 增加的线程已经虚拟内存的消耗. 即使不在执行任何工作, 线程本身也需要使用一定的虚内内存.

这一问题在.NET FRAMWORK 4.5中得到了一定的改进.

当请求到来时, 同样由两个线程来提供服务. 一个线程是来自于CLR的ThreadPool的线程. 这是一个Worker Thread用于接收.svc页面的访问请求. 另外一个线程是 I/O 线程, 用于执行WCF的逻辑. 当请求递交给IOCP之后, Worker Thread并没有一直处于等待状态, 而将已经创建好的HttpContext固定在适当的位置. 它会PINNED在一个HandleTable (strong handle). 以确保这个HttpContext不会被意外的回收. 然后 这个Worker Thread会回到线程池等待分配下一个工作.

在IOCP完成工作需要将结果返回给客户端的时候, 线程池会调度一个线程将对应的HttContext重新拾起, 将需要返回的结果返回给客户端.

下面的内容是.NET FRAMWORK 4.5上的运行时态的示例.

执行WCF请求的线程并没有太多的变化. 从Managed的CALL STACK上看, 它依然是一个IOCP, 并且最后Call到了我们的示例代码中进行了休眠.

主要的区别在于, 我们虽然能找到与之相关的HttpContext, 然后这个HttpContext当前并没有执行在任何一个线程上.在完成IOCP的调用后, 该Worker Thread已经返回了线程池.

0:015> !clrstack -n
OS Thread Id: 0x4278 (15)
        Child SP               IP Call Site
0000005eeee7e098 00007ff9ef2baeca [HelperMethodFrame: 0000005eeee7e098] System.Threading.Thread.SleepInternal(Int32)
0000005eeee7e190 00007ff9e025f399 System.Threading.Thread.Sleep(Int32)
0000005eeee7e1c0 00007ff981ef011b WCFSite.Service1.GetData(Int32)
0000005eeee7e210 00007ff981ee0207 DynamicClass.SyncInvokeGetData(System.Object, System.Object[], System.Object[])
0000005eeee7e250 00007ff9d731f2e2 System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(System.Object, System.Object[], System.Object[] ByRef)
0000005eeee7e430 00007ff9d731b825 System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(System.ServiceModel.Dispatcher.MessageRpc ByRef)
0000005eeee7e7e0 00007ff9d731b020 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(System.ServiceModel.Dispatcher.MessageRpc ByRef)
0000005eeee7e890 00007ff9d731a70b System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(System.ServiceModel.Dispatcher.MessageRpc ByRef)
0000005eeee7ea70 00007ff9d731911e System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean)
0000005eeee7eb30 00007ff9d731866e System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(System.ServiceModel.Channels.RequestContext, Boolean, System.ServiceModel.OperationContext)
0000005eeee7ef10 00007ff9d73168b2 System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(System.ServiceModel.Channels.RequestContext, System.ServiceModel.OperationContext)
0000005eeee7ef90 00007ff9d73163fb System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(System.IAsyncResult)
0000005eeee7eff0 00007ff9d6c3c001 System.Runtime.IOThreadScheduler+ScheduledOverlapped.IOCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
0000005eeee7f050 00007ff9d6c3bf80 System.Runtime.Fx+IOCompletionThunk.UnhandledExceptionFrame(UInt32, UInt32, System.Threading.NativeOverlapped*)
0000005eeee7f0b0 00007ff9e0275db6 System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
0000005eeee7f268 00007ff9e1430453 [GCFrame: 0000005eeee7f268]
0000005eeee7f438 00007ff9e1430453 [DebuggerU2MCatchHandlerFrame: 0000005eeee7f438]
0000005eeee7f5d8 00007ff9e1430453 [ContextTransitionFrame: 0000005eeee7f5d8]
0000005eeee7f7f8 00007ff9e1430453 [DebuggerU2MCatchHandlerFrame: 0000005eeee7f7f8]

0:015> !aspxpagesext
Address          Completed Timeout Time (secs) ThreadId ReturnCode Verb Url
================ ========= ======= =========== ======== ========== ==== =============
0000005eef0540d8        no   11647           7      NO THREAD ID 200 POST /Service1.svc

HandleTable:
    0000005eee5913c0 (strong handle)
    -> 00000061ef0a0460 System.Threading.Thread
    -> 00000061ef031d60 System.Runtime.Remoting.Contexts.Context
    -> 00000061ef031a28 System.AppDomain
    -> 00000060eef67ac0 System.AssemblyLoadEventHandler
    -> 00000060eef679e8 System.Web.Compilation.MemoryBuildResultCache
    -> 00000061ef094cc8 System.Web.Caching.CacheMultiple
    -> 00000061ef0948f8 System.Web.Caching.CacheCommon
    -> 00000061ef09aa10 System.Threading.Timer
    -> 00000061ef09aa88 System.Threading.TimerHolder
    -> 00000061ef09aa30 System.Threading.TimerQueueTimer
    -> 00000061ef08ddb0 System.Threading.TimerQueueTimer
    -> 00000061ef08dd50 System.Threading.TimerCallback
    -> 00000061ef08da88 System.Web.RequestTimeoutManager
    -> 00000061ef08dac0 System.Object[]
    -> 00000061ef08dbc0 System.Web.Util.DoubleLinkList
    -> 0000005eef0556d8 System.Web.RequestTimeoutManager+RequestTimeoutEntry
    -> 0000005eef0540d8 System.Web.HttpContext

0000005eeeb115e8 (strong handle)
    -> 0000005eef0545f0 System.Web.RootedObjects
    -> 0000005eef0540d8 System.Web.HttpContext

总结

运行在IIS上的WCF service, 请求实际上会有两个线程在执行这个请求.

  • 一个线程是来自于CLR的ThreadPool的线程. 这是一个Worker Thread用于接收.svc页面的访问请求.
  • 另外一个线程是 I/O 线程, 用于执行WCF的逻辑.

这种模式提高了WCF服务的吞吐量, 也使得WCF具有更高的灵活性.

在.NET FRAMWORK 3.5中, Worker Thread会被挂起, 并且一直等待IOCP的返回. 这中模式造成了Worker Thread的资源浪费. 在 4.5上, 这一模式得到了改进. Worker Thread在调用IOCP之后会回到线程池. 在必要的时候线程池会重新分配线程进行下一步的操作.

参考资料 :

WCF Request Throttling and Server Scalability

WCF service may scale up slowly under load

Synchronization Contexts in WCF

What You Need To Know About One-Way Calls, Callbacks, And Events

Need sample fire and forget async call to WCF service

探讨 : Host在IIS上的WCF Service的执行方式的更多相关文章

  1. [.NET] WCFDataService项目host到IIS上碰到的一个问题:数据库未能打开

    今天在尝试重现OP一个问题的,遇到了一个新的问题. 项目坏境: WCF Data Service 5.6 Entity Framewrok 5(不用6的原因时要重新配置WCF项目) SQL Serve ...

  2. PyCharm上unittest 测试用例两种执行方式

    每次讲到unittest测试框架的时候,经常有同学在群里反映,为啥我的运行不是按照我往suite里添加的用例顺序执行的,为什么别人的能跑出来报告,我的就不行... 当然,首先确认代码是OK的,如果代码 ...

  3. 托管在IIS上的wcf,在启动的时候,写log

    https://blogs.msdn.microsoft.com/wenlong/2006/01/11/how-to-initialize-hosted-wcf-services/ Using App ...

  4. IIS上发布WCF发布服务,访问不到

    1 环境是IIS7,发布WCF发布服务,访问不到. 一种原因站点自动生成“程序应用池”和站点的Framwork版本不一致. 解决的办法:新建一个“程序应用池”,然后站点指向这个新建的“程序应用池”

  5. WCF服务部署到IIS上,然后通过web服务引用方式出现错误的解决办法

    本文转载:http://www.cnblogs.com/shenba/archive/2012/01/06/2313932.html 昨天在用IIS部署一个WCF服务时,碰到了如下错误: 理解了文档内 ...

  6. Deploying an Internet Information Services-Hosted WCF Service

    Deploying an Internet Information Services-Hosted WCF Service .NET Framework 4   Other Versions .NET ...

  7. ASP.NET MVC提交一个较复杂对象至WCF Service

    前一篇<jQuery.Ajax()执行WCF Service的方法>http://www.cnblogs.com/insus/p/3727875.html 我们有练习在asp.net mv ...

  8. .net core 在IIS上发布502问题

    本来迁移一个项目到.net core就是一件体力活,要找各种替代包,还有一些函数/属性的不支持 总之很头疼... 不要问我为什么用了.net core还要Host在IIS上,国内用.net的公司普遍都 ...

  9. WCF Service部署在IIS上

    环境vs2010,WCF应用程序.如何将WCF部署在IIS上. 第一步:右键点击项目,选择生成部署包. 第二步:在你项目所在的文件目录下找到Package文件夹,这就是我们的部署包所在的地方.在这个p ...

随机推荐

  1. 解决VS 于 致命错误 RC1015: 无法打开包含文件 &#39;afxres.h&#39; 问题

    在试验VS2010当一个问题困扰了我,它是开放的c++项目达产后,rc的dialog入口.您不能拖动控制,让我疯狂... 而最有发言权的是在线Directions问题. .题明显不是这个问题. 于是我 ...

  2. js 正则练习之语法高亮

    原文:js 正则练习之语法高亮 学了几天正则,差不多该总结整理写成果了,之前就想写语法高亮匹配来着,不过水平不够,看着例子都不理解.今天就分析下 次碳酸钴 和 Barret Lee 语法高亮实现. 先 ...

  3. 回想一下著名的BigTable论题

    GFS捕捉一些业务场景的分布式文件系统的需求.很自然.此外还有一些与他们一些业务或依赖于文件系统是不那么容易,他们需要一个分布式数据库系统. BigTable那是,Google结构化数据处理的需求而产 ...

  4. 【百度地图API】如何制作泡泡放大镜?

    原文:[百度地图API]如何制作泡泡放大镜? 任务描述: 我不喜欢API提供的缩放控件耶…… 我能不能使用其他方式放大地图勒? 当然阔以啦! 现在就来教大家如何动手制作一个可爱的泡泡放大镜! 使用它, ...

  5. c++中string类的具体解释

    通过在站点上的资料搜集,得到了非常多关于string类使用方法的文档,通过对这些资料的整理和增加一些自己的代码,就得出了一份比較完整的关于string类函数有哪些和如何用的文档了! 以下先罗列出str ...

  6. android studio 添加到项目库中的项目

    工程-对-new module-Android Library-module name和package name 它应该在同一个库被引入. 然后在该文件夹replace新的library 在gradl ...

  7. 一步一步写算法(之prim算法 上)

    原文:一步一步写算法(之prim算法 上) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面我们讨论了图的创建.添加.删除和保存等问题.今 ...

  8. How to:Installshield判断操作系统是否为64位,并且为操作注册表进行设置

    原文:How to:Installshield判断操作系统是否为64位,并且为操作注册表进行设置 IS脚本操作注册表在64位平台下必须有特殊的设置 if (SYSINFO.bIsWow64) then ...

  9. CSS3实战开发: 纯CSS实现图片过滤分类显示特效

    原文:CSS3实战开发: 纯CSS实现图片过滤分类显示特效 各位网友大家好,今天我要带领大家开发一个纯CSS的图片分类显示的网址导航,单纯看标题大家可能有些困惑,依照以往惯例,我先给大家演示一下实际运 ...

  10. 探讨css中repaint和reflow

    (个人blog迁移文章.) 前言: 页面设计中,不可避免的需要浏览器进行repaint和reflow.那到底什么是repaint和reflow呢.下面谈谈自己对repaint和reflow的理解,以及 ...