WCF回调,代理和线程安全

时间:2012-07-04 10:40:12

标签: c# .net multithreading wcf thread-safety

如果配置为为每个新客户端创建新服务实例的WCF双工服务(NetTcpBinding)(请参阅pattern publish-subscribe),您可以获取每个服务实例的特定回调实例。由于创建了不同的实例,因此可以同时从不同的线程调用属于不同回调的方法。

  • 如果多个线程尝试在同一个回调上调用相同的方法,会发生什么?
  • 如果他们尝试调用不同的方法而不是同一个回调会发生什么?
  • 我们应该管理来自多个线程的这些方法的并发访问吗?在这两种情况下?

现在考虑与服务通信的客户端:为了确保客户端可以使用该服务,您必须实例化一个新的代理,并且为了调用服务中定义的方法,您必须调用相应的方法代理人。

  • 如果多个线程尝试在同一代理实例上调用相同的方法会发生什么?
  • 如果他们尝试调用不同的方法但是同一代理实例会发生什么?
  • 我们应该管理来自多个线程的这些方法的并发访问吗?在这两种情况下?

1 个答案:

答案 0 :(得分:6)

大多数问题的答案取决于您如何管理服务的并发性。没有明确的答案,因为它取决于您为ConcurrencyModeInstanceContextMode设置的内容。 WCF的并发管理将使您能够微调服务的线程行为和性能。关于concurrency management is available on MSDN的长篇大论(但非常详细)。

InstanceContextMode允许您定义应如何实例化您的服务。对于执行大量繁重工作和处理大量呼叫的服务,一般的想法是使用PerCall实例化,因为此设置每次都会在单独的服务实例上处理传入的客户端请求。

主要播放器

ConcurrencyMode将允许您定义在给定时间有多少线程可以访问服务实例。在ConcurrencyMode=Single中,一次只能有一个线程访问服务实例。这还取决于您是否已启用SynchronizationConext,如果SynchronizationConext=true,则如果您的服务正在回答其他请求,则客户端呼叫将排队。因此,传入的服务呼叫将排队,直到首先处理前面的呼叫。使用ConcurrencyMode=Multiple设置,允许任意数量的线程访问服务实例,这意味着您的服务可以响应尽可能多的调用,因为线程池中有多少线程(与CPU功率直接相关)可用。多并发模式的问题是,您的服务在接收和响应调用的顺序中很多都不那么可靠,因为默认情况下SynchronizationContext将被设置为false,因此不会管理状态。关于concurrency modes and thread safety is available on MSDN的简短摘要。

这些设置会在与InstanceContext模式结合使用时影响您的服务性能,请参阅this pretty nice article which explores various concurrency modes and instance context settings and their effects on performance(虽然看起来结果仅在自托管环境中,但可能不太具有代表性在IIS中托管时会得到的时间。)

管理服务并发性的方式将极大地影响其性能。理想情况下,您希望尽可能多地提供线程(尝试增加ThreadPool的最小线程数)到您的服务,并且只要您的服务具有可用的计算资源,就可以避免传入服务调用排队。但过度使用多线程会牺牲状态管理和回答客户请求的顺序。