配置IClientMessageInspector后,WCF服务async/await调用丢失HttpContext问题咨询
问题:未使用
ConfigureAwait(false)的async/await场景下,带IClientMessageInspector的WCF服务上下文同步问题 我们的项目基于.NET Framework 4.5+,用WcfUtils生成了包含异步方法的WCF代理类。在web.config的system.serviceModel节点中配置了自定义的BehaviourExtensionElement,用来注册一个实现IClientMessageInspector的自定义检查器。这个检查器的AfterReceiveReply方法需要访问HttpContext.Current.Items[stringKey]。
现在遇到的问题是:尽管整个执行路径都没用到ConfigureAwait(false),但在AfterReceiveReply方法里HttpContext.Current始终为null。日志显示,调用base.Channel.MyMethod异步方法的前后都存在上下文(因为WcfUtil生成的代理不使用await,只返回Task)。搜了大量资料,没找到关于MessageInspector存在时异步延续上下文的具体说明,搞不懂为什么它的同步机制和主调用不一样。
编辑1:添加中间检查器验证
我创建了一个虚拟的MessageInspector,发现所有await调用进入检查器时都没有上下文:当前认证用户变成了应用池用户,HttpContext.Current为null,执行堆栈如下:
à MyNamespace.InTheMiddleMessageInspector.AfterReceiveReply(Message& reply, Object correlationState) dans D:\Builds\sfpauw14759_1\_work\379\s\Client\AccueilClient\SX00.SXCLT00A.AccueilClient\InTheMiddleMessageInspector.cs:ligne 76 à System.ServiceModel.Dispatcher.ImmutableClientRuntime.AfterReceiveReply(ProxyRpc& rpc) à System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc) à System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result) à System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass7_0`1.<CreateGenericTask>b__0(IAsyncResult asyncResult) à System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization) à System.Threading.Tasks.TaskFactory`1.<>c__DisplayClass44_0`3.<FromAsyncImpl>b__0(IAsyncResult iar) à System.Runtime.AsyncResult.Complete(Boolean completedSynchronously) à System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.FinishSend(IAsyncResult result, Boolean completedSynchronously) à System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.SendCallback(IAsyncResult result) à System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) à System.Runtime.AsyncResult.Complete(Boolean completedSynchronously) à System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelAsyncRequest.OnGetResponse(IAsyncResult result) à System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) à System.Net.LazyAsyncResult.Complete(IntPtr userToken) à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) à System.Net.ContextAwareResult.Complete(IntPtr userToken) à System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken) à System.Net.HttpWebRequest.ProcessResponse() à System.Net.HttpWebRequest.SetResponse(CoreResponseData coreResponseData) à System.Net.ConnectionReturnResult.SetResponses(ConnectionReturnResult returnResult) à System.Net.Connection.ReadComplete(Int32 bytesRead, WebExceptionStatus errorStatus) à System.Net.LazyAsyncResult.Complete(IntPtr userToken) à System.Net.ContextAwareResult.Complete(IntPtr userToken) à System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken) à System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) à System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
编辑2:离开MessageInspector后上下文恢复正常
返回到主代码分支时,上下文恢复正常,此时执行堆栈如下:
à MyNamespace.MyClass.<MyMethodAsync>d__5`2.MoveNext() à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) à System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run() à System.Web.Util.SynchronizationHelper.SafeWrapCallback(Action action) à System.Threading.Tasks.Task.Execute() à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) à System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot) à System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution) à System.Threading.ThreadPoolWorkQueue.Dispatch()
看起来问题出在ASP.NET调用MessageInspector的方式上。
内容的提问来源于stack exchange,提问作者bkqc
相关产品推荐
相关产品推荐

