Cinchoo – ChoSynchronizedEnumerator

ChoSynchronizedEnumerator

This is one another custom enumerator that Cinchoo framework provides. ChoSynchronizedEnumerator is a custom enumerator iterates over collection items synchronized way in multi-threaded applications.

How to use

1. Add reference to Cinchoo.Core.dll assembly

2. Namespace Cinchoo.Core.Collections.Generic or Cinchoo.Core.Collections

Using it on Generic Collections

Use Cinchoo.Core.Collection.Generic namespace.

Sample 1: Here we will see how to use it on List<> object,

Below sample iterates over List<> object by two threads simultaneously.

static void Main(string[] args)
{
    object syncRoot = new object();
    List<string> symbols = new List<string>();

    for (int x = 0; x < 5; x++)
        symbols.Add(String.Format("ITEM{0}", x));

    ManualResetEvent evt = new ManualResetEvent(false);
    for (int z = 0; z < 2; z++)
    {
        ThreadPool.QueueUserWorkItem((state) =>
            {
                Thread.CurrentThread.Name = String.Format("Thread_{0}", state);
                evt.WaitOne();
                int counter = 0;
                foreach (string symbol in new ChoSynchronizedEnumerator<string>(symbols, syncRoot))
                {
                    Console.WriteLine("{0}. {1} -- {2}", ++counter, symbol, Thread.CurrentThread.Name);
                }
            }, z);
    }

    evt.Set();
    Console.WriteLine("Press any key to continue...");
    Console.ReadLine();
}

When you run the above code, you will see the output consistently all the time as below. In a non-synchronous model, the output will product unpredictable sequence of results.

1. ITEM0 -- Thread_0
2. ITEM1 -- Thread_0
3. ITEM2 -- Thread_0
4. ITEM3 -- Thread_0
5. ITEM4 -- Thread_0
1. ITEM0 -- Thread_1
2. ITEM1 -- Thread_1
3. ITEM2 -- Thread_1
4. ITEM3 -- Thread_1
5. ITEM4 -- Thread_1
Press any key to continue . . .

Sample 2: Here we will see how to use it on Dictionary<> object

Below sample iterates over Dictionary<> object by two threads simultaneously.

static void Main(string[] args)
{
    object syncRoot = new object();
    Dictionary<int, string> dict = new Dictionary<int, string>();

    for (int x = 0; x < 5; x++)
        dict.Add(x, String.Format("VALUE{0}", x));

    ManualResetEvent evt = new ManualResetEvent(false);
    for (int z = 0; z < 2; z++)
    {
        ThreadPool.QueueUserWorkItem((state) =>
            {
                Thread.CurrentThread.Name = String.Format("Thread_{0}", state);
                evt.WaitOne();
                int counter = 0;
                foreach (KeyValuePair<int, string> keyValue in new ChoSynchronizedEnumerator<KeyValuePair<int, string>>(dict, syncRoot))
                {
                    Console.WriteLine("{0}. {1} -- {2}", keyValue.Key, keyValue.Value, Thread.CurrentThread.Name);
                }
            }, z);
    }

    evt.Set();
    Console.WriteLine("Press any key to continue...");
    Console.ReadLine();
}

When you run the above code, you will see the output consistently all the time as below. In a non-synchronous model, the output will product unpredictable sequence of results.

0. VALUE0 -- Thread_0
1. VALUE1 -- Thread_0
2. VALUE2 -- Thread_0
3. VALUE3 -- Thread_0
4. VALUE4 -- Thread_0
0. VALUE0 -- Thread_1
1. VALUE1 -- Thread_1
2. VALUE2 -- Thread_1
3. VALUE3 -- Thread_1
4. VALUE4 -- Thread_1
Press any key to continue . . .

Using it on Non Generic Collections

Use Cinchoo.Core.Collection namespace.

Sample 3: Here we will see how to use it on ArrayList object

Below sample iterates over ArrayList object by two threads simultaneously.

static void Main(string[] args)
{
    object syncRoot = new object();
    ArrayList symbols = new ArrayList();

    for (int x = 0; x < 5; x++)
        symbols.Add(String.Format("ZITEM{0}", x));

    ManualResetEvent evt = new ManualResetEvent(false);
    for (int z = 0; z < 2; z++)
    {
        ThreadPool.QueueUserWorkItem((state) =>
            {
                Thread.CurrentThread.Name = String.Format("Thread_{0}", state);
                evt.WaitOne();
                int counter = 0;
                foreach (string symbol in new ChoSynchronizedEnumerator(symbols, syncRoot))
                {
                    Console.WriteLine("{0}. {1} -- {2}", ++counter, symbol, Thread.CurrentThread.Name);
                }
            }, z);
    }

    evt.Set();
    Console.WriteLine("Press any key to continue...");
    Console.ReadLine();
}

When you run the above code, you will see the output consistently all the time as below. In a non-synchronous model, the output will product unpredictable sequence of results.

1. ZITEM0 -- Thread_0
2. ZITEM1 -- Thread_0
3. ZITEM2 -- Thread_0
4. ZITEM3 -- Thread_0
5. ZITEM4 -- Thread_0
1. ZITEM0 -- Thread_1
2. ZITEM1 -- Thread_1
3. ZITEM2 -- Thread_1
4. ZITEM3 -- Thread_1
5. ZITEM4 -- Thread_1
Press any key to continue . . .

Sample 4: Here we will see how to use it on Hashtable object,

Below sample iterates over Hashtable object by two threads simultaneously.

static void Main(string[] args)
{
    object syncRoot = new object();
    Hashtable dict = new Hashtable();

    for (int x = 0; x < 5; x++)
        dict.Add(x, String.Format("VALUE{0}", x));

    ManualResetEvent evt = new ManualResetEvent(false);
    for (int z = 0; z < 2; z++)
    {
        ThreadPool.QueueUserWorkItem((state) =>
            {
                Thread.CurrentThread.Name = String.Format("Thread_{0}", state);
                evt.WaitOne();
                foreach (DictionaryEntry dictEntry in new ChoSynchronizedEnumerator(dict, syncRoot))
                {
                    Console.WriteLine("{0}. {1} -- {2}", dictEntry.Key, dictEntry.Value, Thread.CurrentThread.Name);
                }
            }, z);
    }

    evt.Set();
    Console.WriteLine("Press any key to continue...");
    Console.ReadLine();
}

When you run the above code, you will see the output consistently all the time as below. In a non-synchronous model, the output will product unpredictable sequence of results.

4. VALUE4 -- Thread_0
3. VALUE3 -- Thread_0
2. VALUE2 -- Thread_0
1. VALUE1 -- Thread_0
0. VALUE0 -- Thread_0
4. VALUE4 -- Thread_1
3. VALUE3 -- Thread_1
2. VALUE2 -- Thread_1
1. VALUE1 -- Thread_1
0. VALUE0 -- Thread_1
Press any key to continue . . .

PS: Please be careful about using this enumerator, you must dispose the enumerator to order to avoid contention, deadlock issues.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s