我在 IIS 中托管我的 .NET 4.5 WCF 服务。有一条名为“BusinessContext”(BC)的信息存储在 OperationContext.Current 实例中,因此下游的任何逻辑都可以访问它。
在我引入 async/await 之前一切正常,我遇到了这个问题。@stephen-cleary 提到 ASP.NET 使用异步友好的 AspNetSynchronizationContext 来保持 HttpContext.Current 跨线程。由于我在 IIS 中托管,我认为我应该能够利用 WCF 中的 AspNetSyncCtx,并使用 HttpContext.Current 而不是 OperationContext 来存储 BC。
我从头开始创建了一个 WCF 服务,它在 Web.config 中默认设置了 targetFramework = 4.5、aspnet:UseTaskFriendlySynchronizationContext = true 和 aspNetCompatibilityEnabled = true。我还在我的服务中添加了 AspNetCompatibilityRequirements = Required。
在运行时,我看到 HttpContext.Current 在那里,但 SynchronizationContext.Current 为空。在等待之后,HttpContext 变为空,这是预期的,因为没有 SyncCtx。当需要 aspcompatibility 时,不应该将其设置为 AspNetSyncCtx 吗?AspNetSyncCtx 如何在 ASP.NET 中设置?
-- 可能的解决方案。
在@Stephen-cleary 之后,我继续定义了一个自定义 SynchronizationContext 以跨线程保留 OperationContext。
我想听听社区对此实施的意见。谢谢。
public class OperationContextSynchronizationContext : SynchronizationContext
{
public override void Post(SendOrPostCallback d, object state)
{
OperationContext opCtx = OperationContext.Current;
InternalState internalState = new InternalState()
{
OpCtx = opCtx,
Callback = d,
State = state,
SyncCtx = this
};
ThreadPool.QueueUserWorkItem(new WaitCallback(InternalInvoker), internalState);
}
private void InternalInvoker(object internalState)
{
InternalState internalSt = internalState as InternalState;
SynchronizationContext.SetSynchronizationContext(internalSt.SyncCtx);
using (new OperationContextScope(internalSt.OpCtx))
{
internalSt.Callback.Invoke(internalSt.State);
}
}
private class InternalState
{
public SynchronizationContext SyncCtx { get; set; }
public OperationContext OpCtx { get; set; }
public SendOrPostCallback Callback { get; set; }
public object State { get; set; }
}
}