WCF ClientBase线程安全吗?

时间:2011-01-07 12:18:29

标签: multithreading wcf

我已经实现了ClientBase以使用WCF连接到服务。然后,我在通道上调用一种方法与服务进行通信。

base.Channel.CalculateSomething();

这个调用线程是安全的还是应该在运行多个线程时锁定它?

由于

4 个答案:

答案 0 :(得分:15)

这里对答案的后续评论也让我不确定,所以我做了一些挖掘。以下是ClientBase<T>是线程安全的一些确凿证据 - this blog post讨论了如何在存在同时由多个线程使用的单个客户端代理的情况下正确执行WCF服务(大胆强调的是原文):

  

...但是,如果满足以下条件,则有一种情况:在PerCall服务上将ConcurrencyMode设置为Multiple可以增加服务的吞吐量:

     
      
  1. 客户端是多线程的,并使用相同的代理从多个线程调用您的服务。

  2.   
  3. 客户端和服务之间的绑定是具有会话的绑定(例如,netTcpBinding,wsHttpBinding w / Reliable Session,netNamedPipeBinding等)。

    < / LI>   

此外,这篇文章中的证据似乎与Brian的另外说法相矛盾,即WCF 序列化任何多线程请求。该帖子显示了来自同时运行 的单个客户端的多个请求 - 如果<{strong> ConcurrencyMode.Multiple并使用InstanceContextMode.PerCall

关于此方法的性能影响以及一些替代方案,还有一些额外的讨论here

答案 1 :(得分:12)

是的,它是线程安全的。但是,您应该知道,当使用相同的CalculateSomething实例从多个线程调用时,WCF将自动序列化ClientBase的执行。因此,如果您期望CalculateSomething同时运行,那么您将不得不重新考虑您的设计。有关为CalculateSomething方法创建异步API的一种方法,请查看this answer

答案 2 :(得分:3)

是调用通道上的方法是线程安全的(从客户端角度来看 - 服务角度取决于服务实现)。您可以并行地从多个线程调用此方法。甚至自动生成代理也可以为异步调用创建方法。

答案 3 :(得分:0)

可能引起关注的人。 WCF客户端基本可以是线程安全的,至少在此配置中是这样。我没有尝试其他配置。

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IWcfCallbacksContract), Namespace = "http://wcf.applicatin.srv/namespace")]
public interface IWcfContract
{
    [OperationContract]
    CompositeReturnObject GetServerObject();
}

服务:

public CompositeReturnObject GetServerObject()
{
    CompositeReturnObject ret = new CompositeReturnObject("Hello");
    Thread.Sleep(10000); // Simulating long call
    return ret;
}

客户:

private void GetData_Click(object sender, RoutedEventArgs e)
{
    Console.WriteLine("Task 1 start: " + DateTime.Now.ToString("HH:mm:ss"));

    Task.Factory.StartNew(() => {
        var res = _proxy.GetServerObject();
        Console.WriteLine("Task 1 finish: " + DateTime.Now.ToString("HH:mm:s"));
        Console.WriteLine(res.ToString());
        return;
    }
    );

    Thread.Sleep(2000);

    Console.WriteLine("Task 2 start: " + DateTime.Now.ToString("HH:mm:ss"));

    Task.Factory.StartNew(() => {
        var res = _proxy.GetServerObject();
        Console.WriteLine("Task 2 finish: " + DateTime.Now.ToString("HH:mm:s"));
        Console.WriteLine(res.ToString());
        return;
    }
    );
}

结果:

  

任务1开始:15:47:08
  任务2开始:15:47:10

     

任务1结束:15:47:18
  名称:对象一&#34;你好&#34;

     

任务2结束:15:47:20
  名称:对象一&#34;你好&#34;