简体   繁体   中英

C# Thread Locking Problem

I am creating a solution which has 2 classes

Class A has a public static List object ie public static List<MyClass> classes = new List<MyClass>(); Class B has methods which are running using System.Threading.Timer and call methods of class A on timely intervals

Class A has two methods Method 1: Update the static List - Finds an item and increment its property eg

classes[0].Id = i++;

Method 2: Return the static List

But I keep getting exception that List cannot be modified.

I want to ensure that only one method is locking the classes object at one time. What can I do to achieve it? lock(this) or lock(classes) didn't work.

Exception is along the lines that

list cannot be modifed when it is being enumerated.

It points to the line where classes[0].Id is incremented

Code is:

for (int i = 0; i< classes.Count;i++)
{
if (classes[i].Name == this.NameToFind)
{
classes[i].Id = n++;
}

}

Please note that I want to modify classes list object as the updated object is being returned by the other method.

According to some of the comments on the answers Class A is a Wcf Service and class B is a consuming the service. Those details could have been potentially important as whatever is being returned undergoes serialization.

From what you are describing about the exception, I think we are missing details. You shouldn't be getting that error with out something that uses an enumerator.

As to locking, it sounds like you need a private static object to lock on (since I'm guessing you want to synchronize operations on that static list across instanced wcf calls), but it depends on how you setup your wcf concurrency mode. There are likely more efficient ways to deal with the synchro than the below example, but with what I know it's all I can do. Make sure that anything that touches the private list does so inside the static lock. You probably should look into a reader writer slim lock http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

(handwritten)

class A
{
     private static readonly object listLock = new object();
     private static List<MyClass> classes = new List<MyClass>();

     public void Method1()
     {
          lock(listLock)
          {
               //update here
          }
     }

     public List<MyClass> Method2()
     {
          lock(listLock)
          {
               return classes;
          }
     }

}

It sounds like class A should expose less of it's internals. You've not said much about the design but would this (or similar work)

class A{
  List<MyClass> _list = new List<MyClass>();
  object _lock = new object();
  public void Increment(int index){
     lock(_lock) {/*find item and increment */}
  } 
}

Ideally there would be no static state, B (your message pump) would have access directly or via an interface to an instance of A. If you really need static then make _list and _lock static (but I don't like that).

As already asked, there needs to be more info on the exception

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM