gpt4 book ai didi

wcf - 使用 IIS 中托管的 WCF 中的 AspNetSynchronizationContext

转载 作者:行者123 更新时间:2023-12-04 13:44:01 26 4
gpt4 key购买 nike

我在 IIS 中托管我的 .NET 4.5 WCF 服务。OperationContext.Current 实例中存储了一条名为“BusinessContext”(BC) 的信息,以便下游的任何逻辑都可以访问它。

一切正常,直到我引入 async/await,然后我遇到了 this issue . @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吗?如何在 ASP.NET 中设置 AspNetSyncCtx?

-- 可能的解决方案。

关注@Stephen-cleary 的 here我继续定义了一个自定义 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; }
}
}

最佳答案

我遇到了您提到的问题(错误?),即使使用 HttpContext.Current 也没有在 IIS 中托管的 WCF 服务中与 async 代码一起流动aspNetCompatiblity 已启用且需要。

我的项目使用 LogicalCallContextCallContext.LogicalSetDataCallContext.LogicalGetData,正如 Stephen Cleary 在 this blog post 中所描述的那样.我认为设置/获取您的业务上下文在您的情况下会非常有效,并且可能比自定义 SynchronizationContext 更轻量且概念上更简单。在您的情况下,您无论如何都必须在某处设置您的业务上下文......不妨将其设置为 LogicalCallContext 我相信一切都会好起来的。

我将更详细地解释我的个人“解决方案”,但我承认它有点老套,因为我手动流动整个 HttpContext 对象(并且仅在 WCF 方法中)。但是您的自定义上下文对象的情况似乎更合适。

在我继承的 ASP.NET Web 应用程序中,对 HttpContext.Current 的调用散布在整个业务逻辑中(不理想)。显然,在我希望应用程序中的几个 WCF 方法成为 async 之前,该项目运行良好。

业务逻辑中的许多调用将来自 ASP.NET 页面加载等,其中一切正常。

我通过创建一个小助手类 ContextHelper 解决了(笨拙?)我在 .NET 4.5 中的问题,并将对 HttpContext.Current 的所有调用替换为 ContextHelper .CurrentHttpContext.

public class ContextHelper
{
public static void PrepareHttpContextFlow()
{
CallContext.LogicalSetData("CurrentHttpContext", HttpContext.Current);
}

public static HttpContext CurrentHttpContext
{
get
{
return HttpContext.Current ??
CallContext.LogicalGetData("CurrentHttpContext")
as HttpContext;
}
}
}

现在,只要定义了 HttpContext.Current,我的辅助方法本质上就是空操作。

为了完成这项工作,我的 WCF 调用的入口点必须在第一次调用 await 之前调用 PrepareHttpContextFlow 方法,这无疑是有问题的,也是我认为的主要原因这是一场恶作剧。

在我的例子中,由于我需要一些其他手动调用来添加逻辑堆栈信息以添加逻辑堆栈信息以减轻使用 async 时丢失的错误日志记录上下文(因为物理堆栈信息在这种情况下,异常对于错误日志不是很有用)。所以至少如果我记得做一个“准备异步”调用,我应该记得做另一个:)

关于wcf - 使用 IIS 中托管的 WCF 中的 AspNetSynchronizationContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18520290/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com