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.