Is WCF ClientBase thread safe?
I have implemented ClientBase to use WCF to connect to a service. I'm then calling a method on the channel to communicate with the service.
base.Channel.CalculateSomething();
Is this call thread safe or should I lock arou开发者_如何转开发nd it when running multiple threads?
Thanks
The follow-up comments on the answers here had me uncertain as well, so I did some more digging. Here is some solid evidence that ClientBase<T>
is thread-safe - this blog post discusses how to make a WCF service perform properly in the presence of a single client proxy being used by multiple threads simultaneously (the bold emphasis is in the original):
... However, there is a scenario where setting ConcurrencyMode to Multiple on a PerCall service can increase throughput to your service if the following conditions apply:
The client is multi-threaded and is making calls to your service from multiple threads using the same proxy.
The binding between the client and the service is a binding that has session (for example, netTcpBinding, wsHttpBinding w/Reliable Session, netNamedPipeBinding, etc.).
Also, the evidence in this post seems to contradict Brian's additional remark that WCF serializes any multi-threaded requests. The post shows multiple requests from a single client running simultaneously - if ConcurrencyMode.Multiple
and InstanceContextMode.PerCall
are used.
There is some additional discussion here regarding the performance implications of this approach as well as some alternatives.
Yes, it is thread-safe. However, you should know that WCF will automatically serialize the execution of CalculateSomething
when it is called from more than one thread using the same ClientBase
instance. So if you were expecting CalculateSomething
to run concurrently then you will have to rethink your design. Take a look at this answer for one approach to creating an asynchronous API for the CalculateSomething
method.
Yes calling the method on the channel is thread safe (from the client perspective - service perspective depends on service implementation). You can call this method from multiple threads in parallel. Even autogenerating proxy will offer you to create methods for asynchronnous calls.
To Whom It May Concern. WCF Client base can be thread safe, at least in this configuration. I did not tried other configurations.
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IWcfCallbacksContract), Namespace = "http://wcf.applicatin.srv/namespace")]
public interface IWcfContract
{
[OperationContract]
CompositeReturnObject GetServerObject();
}
Service:
public CompositeReturnObject GetServerObject()
{
CompositeReturnObject ret = new CompositeReturnObject("Hello");
Thread.Sleep(10000); // Simulating long call
return ret;
}
Client:
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;
}
);
}
And result:
Task 1 start: 15:47:08
Task 2 start: 15:47:10Task 1 finish: 15:47:18
Name: Object one "Hello"Task 2 finish: 15:47:20
Name: Object one "Hello"
精彩评论