我已经实现了ClientBase以使用WCF连接到服务。然后,我在通道上调用一种方法与服务进行通信。
base.Channel.CalculateSomething();
这个调用线程是安全的还是应该在运行多个线程时锁定它?
谢谢
对这里答案的后续评论也让我不确定,所以我做了一些挖掘。以下是ClientBase<T>
是线程安全的一些确凿证据 - this blog post讨论了如何在多个线程同时使用单个客户端代理的情况下使WCF服务正常执行(大胆强调在原始版本中):
...但是,如果满足以下条件,则可能会在PerCall服务上将ConcurrencyMode设置为Multiple可以增加服务的吞吐量:
- 客户端是多线程的,并使用相同的代理从多个线程调用您的服务。
- 客户端和服务之间的绑定是具有会话的绑定(例如,netTcpBinding,wsHttpBinding w / Reliable Session,netNamedPipeBinding等)。
此外,这篇文章中的证据似乎与Brian的额外评论相矛盾,即WCF序列化任何多线程请求。该帖子显示了同时运行的单个客户端的多个请求 - 如果使用ConcurrencyMode.Multiple
和InstanceContextMode.PerCall
。
关于这种方法的性能影响以及一些替代方案,还有一些额外的讨论here。
是的,它是线程安全的。但是,您应该知道,当使用相同的CalculateSomething
实例从多个线程调用时,WCF将自动序列化ClientBase
的执行。因此,如果您期望CalculateSomething
同时运行,那么您将不得不重新考虑您的设计。查看this answer,了解为CalculateSomething
方法创建异步API的一种方法。
是调用通道上的方法是线程安全的(从客户端角度来看 - 服务角度取决于服务实现)。您可以并行地从多个线程调用此方法。甚至自动生成代理也可以为异步调用创建方法。
敬启者。 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 名称:对象一“你好”
任务2完成:15:47:20 名称:对象一“你好”