33

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 around it when running multiple threads?

Thanks

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Hnas
  • 331
  • 1
  • 3
  • 3

4 Answers4

15

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:

  1. The client is multi-threaded and is making calls to your service from multiple threads using the same proxy.

  2. 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.

Lars Kemmann
  • 5,509
  • 3
  • 35
  • 67
  • 2
    _While channels and clients created by the channels are thread-safe, they might not support writing more than one message to the wire concurrently._ Source: [MS docs](https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/middle-tier-client-applications?view=netframework-4.7.1) – Josef Bláha Jan 04 '18 at 14:06
14

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.

Community
  • 1
  • 1
Brian Gideon
  • 47,849
  • 13
  • 107
  • 150
  • 3
    Could you explain what you mean by: "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." thanks! – Erick Apr 25 '12 at 16:29
  • 4
    It means that WCF will make the calls one after the other, in a sequential manner, and not simultaneously (although they will appear to be done so from a programmatic point of view). – Raphaël Saint-Pierre Jun 05 '13 at 15:07
  • 3
    What is your evidence or reason for saying that it's thread-safe? And how do you know that CalculateSomething is automatically serialized: is it serialized by the client-side ClientBase instance, or on the server/implementation side? I'm asking because the end of [the ClientBase class on MSDN](http://msdn.microsoft.com/en-us/library/ms576141%28v=vs.110%29.aspx) it says that it is not thread-safe. – ChrisW Jan 10 '14 at 18:46
  • @ChrisW: Hmm...you have me doubting my answer now. Actually, the documentation flat out contradicts my answer. But, on the other hand, the calls really are serialized if I remember correctly. Man, it has been a long time and my recollection of the question and doing WCF in this manner are blurry at best. – Brian Gideon Jan 12 '14 at 04:29
3

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.

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • 1
    What is your evidence or reason for saying that it's thread-safe? I'm asking because the end of [the ClientBase class on MSDN](http://msdn.microsoft.com/en-us/library/ms576141%28v=vs.110%29.aspx) it says that it is not thread-safe. – ChrisW Jan 10 '14 at 18:42
  • @ChrisW: That probably means accessing properties of `ClientBase` is not thread safe but call to the service is (or it can be a bug in documentation - that is not so rare). First of all you can make a call without client base - you need just a channel. I don't have any evidence. I just believe that calling remote service does not need to store any global shared data - otherwise whole client side of WCF would be terribly bad designed. – Ladislav Mrnka Jan 11 '14 at 11:44
  • Is the inner 'channel' known to be thread-safe? I imagine that a channel owns some memory buffers and a network socket; and that unless it's explicitly designed to support concurrent users (e.g. by sequencing their requests), it would be disastrous if two try to write to the memory and socket simultaneously. – ChrisW Jan 11 '14 at 12:17
  • @ChrisW: Channel uses just common .NET implementation for specific transport protocol. For example for HTTP it will create a new `HttpWebRequest` instance for every call. I strongly believe that making calls is thread safe operation because each call should be handled in isolation - there may be some shared data, for example security context but I hope this is handled. Changing anything on `ClientBase` may not be thread safe - on the other hand if I remember it correctly, some changes can be done only before you make a first call. – Ladislav Mrnka Jan 12 '14 at 13:47
  • 2
    In the last two years have you changed your "*strongly believe*" and "*hope*" to "*know*"? It would be nice to have a primary source that explicitly said that (if you have one). – Scott Chamberlain Feb 11 '14 at 14:36
  • @ScottChamberlain: No, I never searched for that and I also never had any issues with concurrency on WCF client classes. – Ladislav Mrnka Feb 11 '14 at 15:36
  • @ChrisW did the ClientBase documentation change? i don't see anything about thread safety – symbiont Mar 14 '23 at 13:48
  • @symbiont I assume so given my comment above but I don't see a mention of thread-safety even in the current .NET Framework version of the documentation, and I don't find the old documentation e.g. using archive.org – ChrisW Mar 14 '23 at 14:10
0

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:10

Task 1 finish: 15:47:18
Name: Object one "Hello"

Task 2 finish: 15:47:20
Name: Object one "Hello"

Ivan ho ho ho
  • 57
  • 3
  • 9
  • 1
    This shows that the calls are not serialized. It could not prove the client is thread safe - it may be a coincidence. – Josef Bláha Jan 04 '18 at 13:29