我一直在研究WCF中的实例化和并发模式,我试图了解是否有任何使用 PerCall 实例和重入并发。在下面的MSDN link中,声明“在PerCall实例化中,并发性不相关”。
并发的使用与实例化模式有关。在PerCall实例化中,并发性是不相关的,因为每个消息都由新的InstanceContext处理,因此InstanceContext中永远不会有多个线程处于活动状态。
但是,我认为可能存在这两种模式(PerCall和Reentrant)必须结合使用的情况。请纠正我和/或给我任何意见。请考虑以下情形:
服务A使用双工MEP。服务A公开一个返回对象的操作合同(即,它不是单向操作)。服务的回调合同还公开了一个返回对象的操作合同(即,它不是单向操作)。服务端点使用wsDualHttp绑定。
操作契约实现在返回之前调用客户端的回调。在这种情况下,如果我将ConcurrencyMode设置为Single,则会发生死锁,无论是否我将ConcurrencyMode设置为Reentrant,一切都按预期工作。
那么,为什么微软说Perconall与PerCall模式无关?
答案 0 :(得分:3)
并发性与有多少线程访问服务实例(InstanceContext)有关。
在percall实例化中,每次调用都会在ASP.Net中创建服务及其相关资源的新实例。当调用结束时,此实例将无效。此外,任何其他线程都无法访问此实例,即使是在同一会话中也是如此。
这就是声明的原因,“在PerCall实例化中,并发性并不重要”。
关于您的方案,在Duplex MEP中,假设A是客户端而B是服务。
当A调用B时,会创建一个Service实例。在双工MEP中,响应必须通过不同的通道(回调通道)发生,并且执行必须跳转到不同的实例(在代理创建期间设置的客户端实例)以便执行。完成此操作后,它必须跳回原始服务实例并从它离开的地方继续。
因此,为了使双工MEP成功,当它跳转到回调通道执行时,需要保持原始服务的实例处于活动状态并且可以重新进入。通过percall实例化,这是不可能的。
这就是双工通道寻找可重入/多重并发和PerSession InstanceContextMode的原因
另请注意,当您未指定实例上下文模式时,默认为PerSession。
答案 1 :(得分:1)
在我看来,MSDN文章简化了一些事情。并发模式确实在PerCall实例化模式中发挥作用。
在博客中,作者必须将PerurrencyMode.Multiple与PerCall一起使用,因为当多个线程使用相同的代理对象调用服务时,使用默认的“Single”将无法正常工作。
在ConcurrencyMode.Single中,如果绑定使用可靠会话,那么即使是PerCall,通道中的所有调用也会排队。
另外,如果服务类中有静态变量怎么办? PerCall没有使它成为线程安全的,正如声明'In PerCall所暗示的那样,并发性是不相关的。“