Enterprise Services (.NET 1.1) Performance Guidelines - Threading

From Guidance Share
Jump to navigationJump to search

- J.D. Meier, Srinath Vasireddy, Ashish Babbar, and Alex Mackman


Use Locks or Mutexes for Granular Synchronization

You use the Synchronization attribute to synchronize access to a class and guarantee that it can be called by only one caller at a time. Serviced components that are configured for transactions and JIT activation are automatically synchronized. Generally, in a server application, you do not need to worry about synchronizing access to a serviced component's class members because by default each component services a single client request and concurrent access does not occur.

If you use a serviced component in a library application from a multithreaded client, you might need synchronized access due to the potential of multiple threads accessing components simultaneously. Also, global variables require separate synchronization.

You use the Synchronization attribute to synchronize access to a class and guarantee that it can be called by only one caller at a time. Serviced components that are configured for transactions and JIT activation are automatically synchronized. Generally, in a server application, you do not need to worry about synchronizing access to a serviced component's class members because by default each component services a single client request and concurrent access does not occur.

If you use a serviced component in a library application from a multithreaded client, you might need synchronized access due to the potential of multiple threads accessing components simultaneously. Also, global variables require separate synchronization.


Using the Synchronization Attribute

You can use the Synchronization attribute only at the class level. This means that all access to an object instance is synchronized. Consider the following example.


  public interface ICustomInterface
  {
     void DoSomething();
  }
  [Transaction(TransactionOption.Required)]
  [Synchronization(SynchronizationOption.Required)]
  [JustInTimeActivation(true)]
  public class CustomClass : ServicedComponent, ICustomInterface
  {
     public void DoSomething();
  }

If you need to synchronize only a small part of your object's code; for example, to ensure that a file or global variable is not accessed concurrently, use the C# Lock keyword instead.


Avoid STA Components

Enterprise Services-serviced components built using Microsoft Visual C# or Microsoft Visual Basic .NET do not exhibit thread affinity because their threading model is set to Both. This setting indicates that the component can be activated in a STA or MTA depending on the caller. The component will be created in the same apartment as its caller.

STA components such as Visual Basic 6.0 components with the Single threading model serialize all callers onto a single STA thread. As a result, an expensive thread switch and cross apartment marshaling occurs every time the object is called.

In addition to the costly thread switches, using STA components creates problems due to the fact that multiple requests made for STA objects are queued until the thread servicing the STA object is free to serve the queued requests.. The required STA thread might already be busy or blocked servicing another request for another component in the same STA. This in turn blocks the caller and creates a significant bottleneck.


References

For more information about threads and apartments, see "Marshaling and COM Apartments" in "Interop Marshaling Overview" of the .NET Framework Developer's Guide on MSDN at http://msdn.microsoft.com/library/en-us/cpguide/html/cpconinteropmarshalingoverview.asp.