I wish to confirm if my working code for showing how a ConcurrentBag collection allows the same collection object to be modified from different threads without any synchronization problems, is acceptable?
I have already written the code that's working. Just wish to get it adheres to best practices. Earlier the same code that used instead a List collections trying to achieve the similar goal is shown to have failed with the error
"System.InvalidOperationException
HResult=0x80131509
Message=Collection was modified; enumeration operation may not execute.
Source=mscorlib
StackTrace:
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at Concurrent_Classes.ListWithMultithreads.Main(String[] args) ....
I am making the comparison between List and ConcurrentBag in a multithreaded scenario to show the utility of using the latter in such a scenario for a course that I am writing on Collections.
This code works:
class ConcurrentBagWithMultithreads
{
ConcurrentBag<string> currencies = new ConcurrentBag<string>();
void CurrencyBag1()
{
currencies.Add("INR");
currencies.Add("NZD");
currencies.Add("AUD");
currencies.Add("USD");
}
void CurrencyBag2()
{
currencies.Add("Euro");
currencies.Add("OMR");
currencies.Add("GBP");
currencies.Add("Dinar");
}
void CurrencyBag3()
{
currencies.Add("CAD");
currencies.Add("Yen");
currencies.Add("Franc");
currencies.Add("Lira");
}
static void Main()
{
ConcurrentBagWithMultithreads concurrentBagWithMultithreads = new ConcurrentBagWithMultithreads();
Thread worker1 = new Thread(concurrentBagWithMultithreads.CurrencyBag1);
Thread worker2 = new Thread(concurrentBagWithMultithreads.CurrencyBag2);
Thread worker3 = new Thread(concurrentBagWithMultithreads.CurrencyBag3);
worker1.Start();
worker2.Start();
worker3.Start();
Console.WriteLine("Testing....");
foreach (string currency in concurrentBagWithMultithreads.currencies)
{
Console.WriteLine($"The currency is = {currency}");
}
Console.Read();
}
}
This code fails: class ListWithMultithreads { List currencies = new List();
void CurrencyList1()
{
currencies.Add("INR");
currencies.Add("NZD");
currencies.Add("AUD");
currencies.Add("USD");
}
void CurrencyList2()
{
currencies.Add("NZD");
currencies.Add("OMR");
currencies.Add("GBP");
currencies.Add("USD");
}
void CurrencyList3()
{
currencies.Add("CAD");
currencies.Add("NZD");
currencies.Add("AUD");
currencies.Add("INR");
}
static void Main(string[] args)
{
ListWithMultithreads listWithMultithreads = new ListWithMultithreads();
Thread worker1 = new Thread(listWithMultithreads.CurrencyList1);
Thread worker2 = new Thread(listWithMultithreads.CurrencyList2);
Thread worker3 = new Thread(listWithMultithreads.CurrencyList3);
worker1.Start();
worker2.Start();
worker3.Start();
foreach (string currency in listWithMultithreads.currencies)
{
Console.WriteLine($"The currency is = {currency}");
}
Console.Read();
}
}
Although I am getting consistent output most of the time with ConcurrentBag collection, occasionally the iteration loop doesn't display a particular set of CurrencyBag items are missed out. In other words about 90% of the times, I am seeing the console brings out all 12 items (which is what should happen always) but rest of the times, there are only eight items on display.
User contributions licensed under CC BY-SA 3.0