我在 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; }
    }
}