-1
private static Thread thread;
private static List<object> items = new List<object>();

static Program()
{
   thread = new Thread(() =>
      {
         foreach (var item in items)
         {
            item.Name = "ABC";
         }
         Thread.Sleep(3600);
      });
   thread.Start();
}

private static void Main(string[] args)
{
   var item = items.Where(i => i.Name == "ABC").FirstOrDefault();
   if(item != null)
      {
         items.Remove(item);
      }

} 

As you see there is thread get started on application started using List perform some operation on the list, and the same List is used by main thread.

when code inside foreach loop of new thread is executing and at the same time foreach loop also get executed it throws error that u can't modify the list.

Any idea how to overcome the issue?

Thanks

BreakHead
  • 10,480
  • 36
  • 112
  • 165
  • 5
    Your code doesn't modify the list, ever... what is your actual code doing? – Jon Skeet Mar 12 '13 at 13:03
  • 3
    You can't modify the list if you are enumerating over it, even if you don't use any threads. – Matten Mar 12 '13 at 13:03
  • There is comment //Perform operation on item – BreakHead Mar 12 '13 at 13:04
  • @Matten I know that :) – BreakHead Mar 12 '13 at 13:04
  • @Matten thats why asking for solution – BreakHead Mar 12 '13 at 13:04
  • 1
    Performing an operation on the item doesn't modify the list. – Matthew Watson Mar 12 '13 at 13:05
  • @BreakHead so what are you trying to do? Maybe your //Perform-comment should show some more details of what you are doing – Matten Mar 12 '13 at 13:05
  • 2
    @BreakHead - Come on man, 1400+ rep and two gold badges and you cant format your question... :) – SwDevMan81 Mar 12 '13 at 13:08
  • You haven't given us enough information. As shown, the code shouldn't do anything because there are no items in the list. How are items being added to the list. What "operation" is being performed on the items? And is anything else modifying the list? – Jim Mischel Mar 12 '13 at 13:08
  • What is your code actually trying to do? What's the goal here? – Servy Mar 12 '13 at 13:55
  • Your primary problem here is that the the thread that's started in the static constructor is iterating the list at the same time the program's main thread (in the `Main` method) is trying to delete items from the list. So the list gets modified and the thread that's iterating the list says, "whoa! you can't do that!" – Jim Mischel Mar 12 '13 at 20:44

3 Answers3

0

The topic you are talking about is Thread-Safeness

To accomplish this, you must use synchronized methods

Edit:

Sorry about that one, of course C#, look here: http://msdn.microsoft.com/en-us/library/ms173179.aspx

It is nearly the same as sync in java, you just have to lock the object for the duration you work with it, that way your threads stay safe

Be aware that while the object is locked, all other threads trying to access the object will have to wait, which can cause a deadlock

Xavjer
  • 8,838
  • 2
  • 22
  • 42
  • This is about C#, not java. Even if the concepts are the same C# doesn't know about the `synchronized` keyword. – Matten Mar 12 '13 at 13:13
0

In your example you are not modifying the collection in the enumeration. However you are modifying the collection outside the enumeration and if that happens during the enumeration you will get the exception InvalidOperationException: Collection was modified.

From MSDN:

A List(T) can support multiple readers concurrently, as long as the collection is not modified. Enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with one or more write accesses, the only way to ensure thread safety is to lock the collection during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.

private static Thread thread;
private static List<object> items = new List<object>();
private Object theLock = new Object();

static Program()
{
  thread = new Thread(() =>
    {
      lock(theLock)
      {
        foreach (var item in items)
        {
          item.Name = "ABC";
        }
      }
      Thread.Sleep(3600);
    });
  thread.Start();
}

private static void Main(string[] args)
{
  lock(theLock)
  {
    var item = items.Where(i => i.Name == "ABC").FirstOrDefault();
    if(item != null)
    {
      items.Remove(item);
    }
  }
} 
Sani Huttunen
  • 23,620
  • 6
  • 72
  • 79
-1

Are you sure this is a Multi-threading issue? List is relativly threadsafe, both the Add and remove methods are fast enough (as far as I know) that MS don't recognize it as an issue, unlike Queue and ConcurrentQueue

Note, that you cannot modify a Collection while looping through it using a foreach so

List<int> integers = new List<int>(new int[] { 1,2,3,4,5,} );
foreach(int i in integers)
    integers.Add(1); // Will throw an InvalidOperationException
Alex Anderson
  • 840
  • 5
  • 11
  • 1
    "A **List** can support multiple readers concurrently, as long as the collection is not modified. Enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with one or more write accesses, **the only way to ensure thread safety is to lock the collection during the entire enumeration**. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization." – Sani Huttunen Mar 12 '13 at 13:10
  • 1
    Corrupting a list by having multiple concurrent writers is childs play. There's no such thing as "relatively thread safe." It's kind of like "a little bit pregnant." Either it supports multiple concurrent writers, or it doesn't. – Jim Mischel Mar 12 '13 at 13:36
  • If you think a list's Add or Remove are actually thread safe, you're quite wrong. The operations are not even fast for large lists, unless you're adding/removing the last item in the list (in which case it will in fact be very quick). Removing the first item means that *every single item in the list* needs to be moved up one position. If you don't see how that could possibly have negative implications, or how that could be done so fast as to appear atomic, then I suggest you stay *far* away from any kinda of multithreaded programming. – Servy Mar 12 '13 at 13:54
  • http://stackoverflow.com/questions/6601611/no-concurrentlistt-in-net-4-0 is where i heard this, they may not be "safe" but I quote: "I found that simply synchronizing adds to a List was faster. Basically, adding to a List is lightning fast already; " – Alex Anderson Mar 12 '13 at 15:43
  • "...simply synchronizing adds to a List" means using a lock, as in `lock(list) { list.Add(item); }` He specifically excludes `RemoveAt` (which, would exclude `Remove`, since `Remove` calls `RemoveAt` after it finds an item), and other methods. He even acknowledges the existence of the lock when he talks about what happens when the list's internal array needs to be resized. – Jim Mischel Mar 12 '13 at 20:40