Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

C#. Static Cache and Multithreading

0.00/5 (No votes)
22 Sep 2017 1  
A few months ago, I had to optimize web portal (classified ad). The portal was built on ASP.NET 1.1. It seemed that portal had two main problems. Here is how I solved them.

A few months ago, I had to optimize web portal (classified ad). The portal was built on ASP.NET 1.1. It seemed that portal had 2 main problems:

  • It failed when it was more than 1 user (Collection was modified, etc.)
  • It returned different data for the same page when I setup more than 1 IIS worker process

The reason is: static cache and other static objects. As far as static objects are the same for all threads and different for every process, they are the reason for both troubles. They conflicted in multithread operations and prevented querying SQL Server “thinking” that data has already been read.

There was no time and resource to redesign and recode the portal. So I needed something clear and powerful.

First, I tried classical methods. I tried to synchronize critical code blocks. But if you have a static collection of collections, this is not really possible. All nested collections are candidates to fail in any part of code.

Next, I tried not to enumerate original lists. I always create copy before enumeration to prevent its modification before enumeration finishes. However, it led to a set of new troubles and I had to get everything back.

And... a fresh idea entered my head. Now it seems quite obvious, but it took a long period to appear...

Look, If we have static cache in the following form:

static Hashtable Objects = new Hashatble();

we do not need to synchronize it. It is enough to make for each thread its own cache. And we easily can do it with CallContext. First, create a thread-safe “static” object store:

public sealed class CallObjects
{
   public enum Names
   {
      STAT_OBJ_1,
      STAT_OBJ_2,
      ......... 
   }

   public static object Get(Names name)
   { 
      return CallContext.GetData(name.ToString());
   }

   public static void Set(Names name, object obj)
   {
      if ( obj == null )
         CallContext.FreeNamedDataSlot(name.ToString()); 
      else
         CallContext.SetData(name.ToString(), obj);
   }
}

Now we can use static property that returns thread-dependent Hashtable:

Hashtable Objects
{
   get {
      Hashtable objects = 
         (Hashtable) CallObjects.Get(CallObjects.Names.STAT_OBJ_1); 
      If ( objects == null ) { 
         objects = new Hashtable();
         CallObjects.Set(CallObjects.Names.STAT_OBJ_1, objects);
      } 
      return objects;
   }
}

This simple modification saved life to the project. And that was great saving of money and time.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here