locked
Thread safety when using chained WCF RIA/WCF services and Windows Service RRS feed

  • Question

  • User-1966014721 posted

    Updated

    I have am not sure that this is the right fourm to post this question on. I have reposted on http://social.msdn.microsoft.com/Forums/en/adodotnetdataservices/thread/343c3332-59d3-40df-84f5-ca821bf69037

    .....

    Hello,

    I have a threading question about the following scenario. This is the first time I have used chained WCF RIA/WCF services with a Windows service to access a lot of data stored in memory. The service must be capable of handling high concurrency for primarily reading data.

    I am using WCF RIA Services for a Silverlight 5 application. On the server, the RIA services are used to access long-running WCF services (the WCF services reside in a Windows service). The WCF services are used to read/write data that is contained in one or more persistent Concurrent Dictionaries.

    The following is an example of the endpoint binding contract that I use in the WCF RIA service methods to communicate with the long-running WCF service.

    <endpoint address="net.tcp://localhost:8732/MemberDataService/"

     binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IMemberDataService"

     contract="MemberDataServiceReference.IMemberDataService" name="NetTcpBinding_IMemberDataService">

     <identity>

      <dns value="localhost" />

     </identity>

    </endpoint>

    Assuming that ConcurrencyMode is set to Multiple for all WCF services, it is my understanding that each WCF RIA/normal WCF service call is thread safe (in of itself) and it lives for as long as necessary to execute the method call. In my scenario, I believe the WCF service chain should be cleaned up (disposed) by the server after each use.

    An example of a typical WCF RIA services call is as follows:

    WCF RIA Service

    [Invoke]

    public ItemType GetItemInformation(string name)

    {

    ... try/catch logic omitted

    using (MemberDataServiceReference.MemberDataServiceClient mdsc = new MemberDataServiceReference.MemberDataServiceClient())

    {

           return = mdsc.GetItem (name);

    }

    ...

    }

    Long-running WCF Service

    The GetItem method uses something similar to the following:

    public ItemType GetItem(string name)

    {

    ... try/catch logic omitted.

           ItemType item = null;

           if (ConcurrentDictionaryData<string, ItemType >.InMemoryContainer.TryGetValue(name, out item))

           {

                  return item;

           }

    ...

    }

    Assumptions:

    1. The GetItemInformation code block above is multithreaded and should be thread safe as shown.
    2. Assuming the endpoint reference is multithreaded to the long-running WCF service; AND each WCF RIA instance gets access to its own instance of the GetItem method; AND the ConcurrentDictionaryData repository is only used for valid concurrent access operations... then the above configuration should be thread safe.

    Questions:

    1. Am I overlooking something in my understanding of these two WCF communications paths?
    2. Any good reference links for how to test high concurrency usages?

    Everything works fine, but we haven’t yet tested for high concurrency use scenarios.

    I would appreciate any/all constructive feedback...

    Thanks...

    Wednesday, February 13, 2013 12:50 PM

Answers

  • User-306339031 posted

    The code looks fine to me. Just do a thorough testing. You can use any Load Testing software to simulate high concurrency. One thing to watch out is timeout at the client (SL) if the RIA calls takes too long to return to the Client.  Silverlight uses underlying Wininet API to make RIA calls and there is a timeout at the Wininet layer (I believe it is 5 mins by default).

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, February 20, 2013 1:07 PM
  • User-1966014721 posted

    Enamul,

    Thanks for taking a look at my code and for your feedback.

    I also have found several links (included below for others with the same question) that would lead me to believe my approach of the two chained WCF services is thread safe. I am using each service with ConcurrencyMode set to multiple and InstanceContextMode set to per call. So I believe that the two WCF services must be thread safe by design according to the documentation that I have read. Since the only method call is to a ConcurrenDictionary method, which also supports thread safe concurrency, the whole chain should also therefore be thread safe by design.

    With respect to load testing software, I am looking for a good product that has reasonable documentation. Some of the ones that I have looked at so far are scant on documentation. Any strong recommendations???

    Useful Links:

    http://blogs.msdn.com/b/rickrain/archive/2009/06/17/wcf-instancing-concurrency-and-throttling-part-2.aspx

    http://msdn.microsoft.com/en-us/magazine/cc163321.aspx

    http://msdn.microsoft.com/en-us/library/orm-9780596521301-02-08.aspx

    Instance Management and Concurrency

    Service-instance thread safety is closely related to the service instancing mode. A per-call service instance is thread-safe by definition, because each call gets its own dedicated instance. That instance is accessible only by its assigned worker thread, and because no other threads will be accessing it, it has no need for synchronization. However, a per-call service is typically state-aware. The state store can be an in-memory resource such as static dictionary, and it can be subject to multithreaded access because the service can sustain concurrent calls, whether from the same client or from multiple clients. Consequently, you must synchronize access to the state store.

    http://msdn.microsoft.com/en-us/library/dd287191.aspx

    All these operations are atomic and are thread-safe with regards to all other operations on the ConcurrentDictionary<TKey, TValue> class. The only exceptions are the methods that accept a delegate, that is, AddOrUpdate and GetOrAdd. For modifications and write operations to the dictionary, ConcurrentDictionary<TKey, TValue> uses fine-grained locking to ensure thread safety. (Read operations on the dictionary are performed in a lock-free manner.) However, delegates for these methods are called outside the locks to avoid the problems that can arise from executing unknown code under a lock. Therefore, the code executed by these delegates is not subject to the atomicity of the operation.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 21, 2013 10:26 AM

All replies

  • User-306339031 posted

    The code looks fine to me. Just do a thorough testing. You can use any Load Testing software to simulate high concurrency. One thing to watch out is timeout at the client (SL) if the RIA calls takes too long to return to the Client.  Silverlight uses underlying Wininet API to make RIA calls and there is a timeout at the Wininet layer (I believe it is 5 mins by default).

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, February 20, 2013 1:07 PM
  • User-1966014721 posted

    Enamul,

    Thanks for taking a look at my code and for your feedback.

    I also have found several links (included below for others with the same question) that would lead me to believe my approach of the two chained WCF services is thread safe. I am using each service with ConcurrencyMode set to multiple and InstanceContextMode set to per call. So I believe that the two WCF services must be thread safe by design according to the documentation that I have read. Since the only method call is to a ConcurrenDictionary method, which also supports thread safe concurrency, the whole chain should also therefore be thread safe by design.

    With respect to load testing software, I am looking for a good product that has reasonable documentation. Some of the ones that I have looked at so far are scant on documentation. Any strong recommendations???

    Useful Links:

    http://blogs.msdn.com/b/rickrain/archive/2009/06/17/wcf-instancing-concurrency-and-throttling-part-2.aspx

    http://msdn.microsoft.com/en-us/magazine/cc163321.aspx

    http://msdn.microsoft.com/en-us/library/orm-9780596521301-02-08.aspx

    Instance Management and Concurrency

    Service-instance thread safety is closely related to the service instancing mode. A per-call service instance is thread-safe by definition, because each call gets its own dedicated instance. That instance is accessible only by its assigned worker thread, and because no other threads will be accessing it, it has no need for synchronization. However, a per-call service is typically state-aware. The state store can be an in-memory resource such as static dictionary, and it can be subject to multithreaded access because the service can sustain concurrent calls, whether from the same client or from multiple clients. Consequently, you must synchronize access to the state store.

    http://msdn.microsoft.com/en-us/library/dd287191.aspx

    All these operations are atomic and are thread-safe with regards to all other operations on the ConcurrentDictionary<TKey, TValue> class. The only exceptions are the methods that accept a delegate, that is, AddOrUpdate and GetOrAdd. For modifications and write operations to the dictionary, ConcurrentDictionary<TKey, TValue> uses fine-grained locking to ensure thread safety. (Read operations on the dictionary are performed in a lock-free manner.) However, delegates for these methods are called outside the locks to avoid the problems that can arise from executing unknown code under a lock. Therefore, the code executed by these delegates is not subject to the atomicity of the operation.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 21, 2013 10:26 AM