我可以在同一个服务中使用PerCall实例化和可重入并发性吗?

本文关键字:并发 实例化 服务 同一个 PerCall 我可以 | 更新日期: 2023-09-27 18:02:11

我一直在研究WCF中的实例化和并发模式,我试图理解是否有任何情况下使用PerCall实例化和可重入并发是有意义的。在下面的MSDN链接中指出"在PerCall实例化中,并发性与无关"。

并发的使用与实例化模式有关。在PerCall实例化中,并发性是不相关的,因为每条消息都由一个新的InstanceContext处理,因此,在InstanceContext中活动的线程永远不会超过一个。

然而,我认为可能存在这两种模式(PerCall和Reentrant)必须结合使用的情况。请纠正我和/或给我任何输入。考虑以下场景:

业务A使用双工MEP。服务A公开了一个返回对象的操作契约(也就是说,它不是一个单向操作)。服务的回调契约也公开了一个返回对象的操作契约(也就是说,它不是一个单向操作)。服务端点使用wsDualHttp绑定。

操作契约实现在返回之前调用客户端的回调。在这种情况下,如果我将ConcurrencyMode设置为Single,则会发生死锁,无论我将ConcurrencyMode设置为Reentrant,一切都如预期的那样工作。那么,为什么微软说并发性与PerCall模式无关呢?

我可以在同一个服务中使用PerCall实例化和可重入并发性吗?

并发性绑定到有多少线程正在访问服务的实例(InstanceContext)。

在percall实例化中,每个调用都创建一个新的服务实例及其相关资源,就像在ASP.Net中一样。当调用结束时,此实例将无效。更重要的是,这个实例不能被任何其他线程访问,即使来自同一个会话。

这就是语句"在PerCall实例化中,并发性是不相关的"的原因。

对于您的场景,在双工MEP中,假设A是客户端,B是服务。

当A调用B时,创建一个Service实例。在双工MEP中,响应必须通过不同的通道(回调通道)发生,并且执行必须跳转到不同的实例(在代理创建期间设置的客户端实例)执行。完成此操作后,它必须跳转回原始服务实例,并从它离开的地方继续。

因此,为了使双工MEP成功,它需要保持原始服务的实例处于活动状态,并且当它跳转到回调通道执行时可重新进入。对于percall实例化,这是不可能的。

这就是为什么双工通道正在寻找可重入/多并发性和会话InstanceContextMode

还要注意,当您不指定实例上下文模式时,默认为PerSession。

在我看来,MSDN的文章简化了事情。并发模式确实在PerCall实例化模式中起作用。

查看这篇博文:http://blogs.msdn.com/b/rickrain/archive/2009/06/17/wcf-instancing-concurrency-and-throttling-part-2.aspx.

在博客中,作者不得不使用ConcurrencyMode。使用PerCall的Multiple,因为当多个线程使用相同的代理对象调用服务时,使用默认的'Single'将不能很好地工作。

请求。如果绑定使用可靠会话,那么通道中的所有调用都将排队,即使是PerCall。

另外,如果在服务类中有静态变量怎么办?PerCall不能使它成为线程安全的,正如语句"在PerCall中,并发性是不相关的"所暗示的那样。