我目前有一个WCF服务,用于执行一些数据库查询和发送邮件。长话短说,这两种方法都是异步使用的,HttpContext.Current
实现中的某个地方。
我最初的问题是,在第一个await
之后,HttpContext.Current
变为空,因此第二个操作失败。我现在在谷歌上搜索了几个小时,我测试了我找到的所有东西......自定义同步上下文,web.config 中的 appSettings 面向 .NET 4.5,启用 ASP.NET 兼容性,但没有任何效果。
然后,我发现了这个SO帖子,谈论CallContext
。基本上,这个想法是 将HttpContext.Current
存储在CallContext
中。我测试了一下,是的,它奏效了。然而,由于我不知道到底是什么CallContext
,我读到了它。
我不确定我是否真的正确理解了所有内容,但在阅读后,我有一个担忧。我可能是错的,但似乎不能保证异步调用完成后恢复的线程与初始线程相同。问题是我在HttpContext
中存储了多个值,我担心第一个方法使用用户 A 值执行,然后,一旦异步调用完成,第二个方法就会使用用户 B 值执行(因为HttpContext
不会相同(。
我想人们会想告诉我只将这些值存储在CallContext
但我在遇到 WCF 问题之前创建了一个完整的架构,所以我不想完全审查它,这就是为什么CallContext
派上用场,因为更改很小。
有人能告诉我我的理论是否正确吗?
WCF是开箱即用的SOA架构,具有多种协议支持,除了您可以扩展自定义所有内容之外,一切都是可配置的。所以得到所有是非常棘手的。只是基础知识:
三种类型的 WCF并发是:
单个:单个请求在给定时刻有权访问 WCF 服务对象。
多个:在此方案中,WCF 服务对象可以在任何给定时刻处理多个请求。
可重入:单个请求线程有权访问 WCF 服务对象,但该线程可以退出 WCF 服务以调用另一个 WCF 服务,也可以通过回调调用 WCF 客户端,然后重新进入而不会死锁。
看起来很简单,但等待它具有与并发不同的实例化模式:
- 每次调用为每个客户端请求创建新的实例上下文(以及服务对象(。
- 每个会话 为每个新的客户端会话创建新的 InstanceContext(以及服务对象(,并在该会话的生存期内进行维护(这需要支持会话的绑定(。
单个实例:单个实例上下文(以及服务对象(处理应用程序生存期内的所有客户端请求。
默认实例模式为"按会话",默认并发模式为"单个
"这意味着对于 WCF 服务,在您更改服务之前,只有一个实例上下文,一次最多允许一个线程处理实例上下文中的消息。希望使用相同的实例上下文的其他线程必须阻塞,直到原始线程退出实例上下文
因此,在您为此进行代码更改并希望它发生之前,您所担心的似乎是不可能的。
有关更多详细信息,请参阅 : MSDN
您应该更改服务,以便它们不依赖于HttpContext.Current
。最好是完全不依赖HttpContext
。
HttpContext.Current
是 UI 线程的服务器端等效项。只是不要在不需要依赖它的代码上使用它。