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

时间:2011-07-14 16:51:01

标签: c# .net wcf

我一直在研究WCF中的实例化和并发模式,我试图了解是否有任何使用 PerCall 实例和重入并发。在下面的MSDN link中,声明“在PerCall实例化中,并发性不相关”。

  

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

但是,我认为可能存在这两种模式(PerCall和Reentrant)必须结合使用的情况。请纠正我和/或给我任何意见。请考虑以下情形:

服务A使用双工MEP。服务A公开一个返回对象的操作合同(即,它不是单向操作)。服务的回调合同还公开了一个返回对象的操作合同(即,它不是单向操作)。服务端点使用wsDualHttp绑定。

操作契约实现在返回之前调用客户端的回调。在这种情况下,如果我将ConcurrencyMode设置为Single,则会发生死锁,无论是否我将ConcurrencyMode设置为Reentrant,一切都按预期工作

那么,为什么微软说Perconall与PerCall模式无关?

2 个答案:

答案 0 :(得分:3)

并发性与有多少线程访问服务实例(InstanceContext)有关。

在percall实例化中,每次调用都会在ASP.Net中创建服务及其相关资源的新实例。当调用结束时,此实例将无效。此外,任何其他线程都无法访问此实例,即使是在同一会话中也是如此。

这就是声明的原因,“在PerCall实例化中,并发性并不重要”

关于您的方案,在Duplex MEP中,假设A是客户端而B是服务。

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

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

这就是双工通道寻找可重入/多重并发和PerSession InstanceContextMode的原因

另请注意,当您未指定实例上下文模式时,默认为PerSession。

答案 1 :(得分:1)

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

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

在博客中,作者必须将PerurrencyMode.Multiple与PerCall一起使用,因为当多个线程使用相同的代理对象调用服务时,使用默认的“Single”将无法正常工作。

在ConcurrencyMode.Single中,如果绑定使用可靠会话,那么即使是PerCall,通道中的所有调用也会排队。

另外,如果服务类中有静态变量怎么办? PerCall没有使它成为线程安全的,正如声明'In PerCall所暗示的那样,并发性是不相关的。“