2011-06-28 82 views
0

我創建具有2類C#螺紋鎖定問題

溶液

類A具有一個公共靜態列表對象即public static List<MyClass> classes = new List<MyClass>(); B類具有使用類A的System.Threading.Timer和調用方法運行方法按時間間隔

A類有兩種方法 方法1:更新靜態列表 - 查找一個項目並增加它的屬性例如

classes[0].Id = i++; 

方法2:返回靜態列表

但我不斷收到異常名單無法修改。

我想確保一次只有一個方法鎖定類對象。我能做些什麼來實現它?鎖(this)或鎖(classes)不起作用。

例外是沿着

list cannot be modifed when it is being enumerated. 

它指向哪裏classes[0].Id遞增

代碼行是行:

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

} 

請注意,我想修改類的列表對象作爲更新的對象正在由另一個方法返回。

+2

什麼是異常消息的確切措辭?你在哪一行代碼中得到它?如果你發佈了更多的代碼,這可能會有幫助,所以我們可以看到發生了什麼。 –

+0

也許你可以嘗試使用不同於List <>的類,可能是[System.Collections.Concurrent](http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx)如果您使用的是4.0,或者至少實現了對列表的某些管理訪問 –

+0

如果迭代列表時列表被修改,則會引發該類型的異常。這可以在foreach塊內的同一個線程上或單獨的線程中。 – eulerfx

回答

0

這聽起來像A類應該暴露少它的內部。你沒有說太多關於設計,但這樣做(或類似的工作)

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

理想的情況下不會有什麼靜態,B(你的消息泵)將直接或通過對實例的接口訪問答:如果你真的需要靜態,那麼使_list和_lock是靜態的(但我不喜歡那樣)。

前面已經提出,需要有例外

+0

_list = new List 每次創建一個新的類對象。我只想在A班的一生中創建一個對象。 A類實際上是一個WCF服務,我的客戶... B類正在調用 – InfoLearner

0

更多信息根據一些對答案的意見,A類是WCF服務和B類是消費服務。這些細節可能是潛在的重要,因爲正在返回的東西會經歷系列化。

從你所描述的例外情況來看,我認爲我們缺少細節。你不應該因爲使用枚舉器的東西而得到這個錯誤。對於鎖定,這聽起來像你需要一個私人靜態對象來鎖定(因爲我猜你想要在該靜態列表上同步跨實例wcf調用的操作),但這取決於你如何設置你的wcf併發模式。有可能比下面的例子更有效的方式來處理同步,但我知道這是我所能做的。確保接觸到私人列表的任何內容都在靜態鎖內進行。你或許應該看看讀寫器超薄鎖http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

(手寫)

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; 
      } 
    } 

}