2010-11-29 2 views
1

요소를 통해 반복되는 객체를 잠그려고합니다. "foreach"를 실행하는 동안 "콜렉션이 수정되었으므로 열거 연산이 실행되지 않을 수 있습니다."라는 예외가 발생하기 때문에 arraylist allThreads는 실제로 잠기지 않습니다. 내가 자물쇠를 다 다루는 줄 알았는데?Lock()이 효과적이지 않습니다.

lock (mApp.allThreads) 
{ 
    foreach (Thread t in mApp.allThreads) 
     if (t.Name == "OpcDAWriter" && t != Thread.CurrentThread) 
      t.Join(); 
} 
+0

allThreads를 수정하는 코드는 어디에 있습니까? 그것은 또한 컬렉션을 잠그고 있습니까? –

답변

0

당신은 t 스레드에 합류, 그래서 아마 mApp.allThreads에서 제거됩니다 또는 참여로 인해 뭔가 다른, 따라서 컬렉션을 수정, 발생합니다. 객체를 accesing 모든 방법은 거기에 고정 될 때

또한, 모든 다른 방법이 그것을 잠글 수없는 개체를 찾고있다해서, 잠금에만 작동합니다. 당신은 즉, 잠금 매개 변수로 외부 개체를 사용하여 시도 할 수 :

private readonly _lock = new object(); 

[...] 
lock(_lock) 
{ 
    foreach.... 
} 

하지만 난 그 아무것도 변경됩니다 의심한다.

3

lock이 당신을 위해 오인했을 수도 있습니다. 이 아니므로 다른 코드가 잠금을 설정 한 객체를 조작하지 못하도록합니다. 그것은 하나의 스레드가 하나의 객체에서 long을 획득하는 것을 막고, 다른 스레드는 잠금을 유지합니다.

다른 스레드가 반복하는 동안 한 스레드가 컬렉션을 조작하지 못하도록하려면 반복 코드와 조작 코드를 동일한 오브젝트에 대해 잠금 lock 블록 내에 넣어야합니다.

간단한 예제 : (이 경우 생성자 제외) 목록에 대한 모든 액세스가 모두 동일한 개체를 잠그는 lock 블록으로 포장하는 방법

class LockDemo 
{ 
    private IList<string> _items; 
    private object _lock = new object(); 
    public LockDemo() 
    { 
     _items = new List<string>(new[] { "one", "two", "three" }); 
    } 

    public void RemoveItem(string item) 
    { 
     lock (_lock) 
     { 
      _items.Remove(item); 
     } 
    } 

    public void DoSomethingThatIteratesOverTheList() 
    { 
     lock (_lock) 
     { 
      foreach (var item in _items) 
      { 
       // do something with item 
      } 
     } 
    } 
} 

알 수 있습니다. 또한이 객체는 목록 자체가 아니라 잠금 목적으로 만 사용되는 객체입니다. 이것은 lock이 객체를 잠그지 않았 음을 보여 주지만, 다른 스레드에 의해 병렬로 실행될 수도 있고 실행되지 않을 수도있는 코드 부분을 제어하는 ​​메커니즘을 제공합니다.

+0

아, 이제 나는 자물쇠의 행동을 이해합니다. (내 _lock 객체의 두 명의 사용자 중 한 명과 함께 사용 된 잠금 만 사용). 큰 설명, 고마워요! – AKZ

관련 문제