0

I am referencing a (black box) dll which has extremely expensive initialization (takes 3-4 seconds). It is used by an asp.net application that has several hundred simultaneous users.

Because of the expensive initialization I cannot use it as an instance variable. My first thought is to store the instance in a static variable and use the c# lock() method to avoid race conditions. This works fine, but obviously the lock() method around a single static variable is going to be inefficient when multiple users want to access the library simultaneously.

I want to implement an object pool so that multiple instances of this library can be employed. I can't use COM+. What is the best way to implement an object pool in c#, .Net 4.5.1, when the pool will be consumed by an asp.net application?

There are many references to this MSDN article suggesting use of a ConcurrentBag, but many say this works best when a single thread is adding/removing items from the pool. In my case multiple threads will be adding/removing items, so this approach does not appear to be the right one for asp.net, but if I am wrong in stating that please correct me: https://msdn.microsoft.com/en-us/library/ff458671(v=vs.110).aspx

I found this answer very informative, but it is dated: C# Object Pooling Pattern implementation

Community
  • 1
  • 1
Tom Regan
  • 3,580
  • 4
  • 42
  • 71
  • 1
    The [accepted answer](http://stackoverflow.com/a/30664859/1144943) in the question you link refers to Roslyn and is just a couple of months old. The implementation of the object pool (one of them) may be found [here](https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/SharedCollections/ObjectPool%601.cs) – Erik Ovegård Nov 04 '15 at 20:43

1 Answers1

1

ConcurrentBag is the optimal structure for a object pool.

You are misinterpreting the advice of "this works best when a single thread is adding/removing items from the pool". A better way to say it would be "A ConcurrentBag works best when the thread removing from the pool has a high chance of being the same thread that put the object in the pool" which is exactly what your object pool will be doing.

The way ConcurrentBag works is each thread has a thread local collection of objects. When you add to the ConcurrentBag it inserts to that thread local collection, when you remove from the ConcurrentBag it first tries to remove from the thread local collection but if it is empty it goes to another thread and removes it from the other thread's collection.

So the reason it is recommend the same thread add as remove is so you don't tie up two lists with locks instead of a single one.

You can even use a single thread to populate the pool then as workers take items out they will steal from the initialization thread's pool but then return it to their own pool pulling from their own pool from then on.

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • Excellent, thank you hitting that nail right on the head. – Tom Regan Nov 04 '15 at 22:18
  • if you would entertain a follow-up question on how exactly to code this for use from an asp.net application: http://codereview.stackexchange.com/questions/109924/using-the-concurrentbag-as-an-object-pool-for-asp-net-application – Tom Regan Nov 05 '15 at 19:42