2013-08-14 2 views
0

병렬 스레딩 타이머가있는 프로그램이 있습니다. 기본적으로이 타이머는 매 10 초마다 메소드를 실행하도록 설정됩니다. 이 메서드는 스레드가 작업을 수행하기 위해 복사본을 만들기 위해 목록을 잠급니다.C# 잠금 또는 잠금 간 장시간 잠기기

private object access = new object(); 
PeriodTask(){ 
    lock(access){ 
     copy = list.Where(e => e.valid).toList(); 
    } 
    foreach (var element in copy) 
     do some not so quick work. 
} 

는 또한 또한 잠금을 요청하는 요소에 대한 정보를 얻을 수있는 방법이있다. 그리고 사본뿐만 아니라 그것을 잠이 목록에서 항목을 추가 및 제거하는 방법이 있기 때문에 내가 잠금을 필요로하는 이유는

informationMethod(){ 
    lock(access){ 
     return list.Select(element => new serializableElement(element)).toList() 

    } 
} 

를 가져옵니다. 그러나 나는 아직 그들을 부르지 않고있다.

내가 겪고있는 문제는 정보 검색 방법이이 클래스의 인스턴스간에 오랜 시간 동안 차단되거나 잠자기 상태라는 것입니다. 이 중 약 10 개가있을 수 있으며 한 번에 2 개 또는 3 개의 액세스 권한을 얻는 것처럼 보이지만 프로세스를 완료하려면 1 분에서 2 분 정도 소요될 수 있습니다. 내가 언급 한 첫 번째 메서드는 타이머에서 실행되는 즉시 잠금을 해제하고 해제해야하지만 다른 스레드는 실행의 주 스레드 임에도 불구하고 실행을 중단합니다.

이러한 클래스의 관리자를 인스턴스화하는 몇 가지 테스트가 있습니다.

//sets up updaters test 
var manager = new manager(config); 
Assert.IsNotNull(manager); 
Assert.IsFalse(manager.UpdatersRunning); 
Assert.AreNotEqual(0, manager.Updaters.Count());//calls the informationMethod on each updater 
manager.Dispose(); 
//This test doesn't even run the period task 


//Waits to start updaters test 
var manager = new StatusObjectManager(config); 
Assert.IsNotNull(manager); 
Assert.AreNotEqual(0, manager.Updaters.Count()); 
Assert.IsFalse(manager.UpdatersRunning); 
Assert.AreEqual(0, manager.Updaters.Count(u => u.Running)); 
manager.StartUpdaters(); 
Assert.IsTrue(manager.UpdatersRunning); 
Assert.AreNotEqual(0, manager.Updaters.Count(u => u.Running)); 
manager.Dispose(); 
//This test runs the period tasks and checks to make sure their running. Or at least 1. 
//THis test takes a long time for the first informationMethod bout but not the other 2. 

The code in the manager looks like this 
return updaters.select(u => new serialUpdater(su)); 

이 목록은 수정되지 않았으므로 잠금이 필요하지 않습니다.

누구에게 무슨 일이 벌어 질지 상상해보십시오. 스레드가 잠금 장치에서 막히고 있는지 또는 비정상적인 시간 동안 잠자고 있는지를 어떻게 알 수 있을지 모르겠습니다.

+0

은 .NET 프레임 워크의 어떤 버전을 사용 할 때

또한, 참조 형식을 인식? –

+0

.NET 4.0, 동시 수집을 사용해야한다고 생각하십니까? 나는 그것을 고려했으나 내 솔루션에 가장 적합한 concurrentbag에는 성능 문제도 있다고 들었다. 그러나 나는 이것이 갈 수 없다면 그냥 가야 할 수도 있습니다. – ProdigousRanger

+0

예, ConcurrentBag에서 생각합니다.

답변

0

여기서 첫 번째 단계는 로깅을 추가하는 것입니다. 잠금 장치의 앞과 안쪽에있는 간단한 Trace.WriteLine을 사용하면 Thread을 읽고 생성하는 중에 Thread.CurrentThread.Name을 가져 오거나 설정할 수 있습니다. 따라서 Thread이 있는지 확인할 수 있습니다.

다음 단계는 깨끗하지는 않지만 더 빠를 것, 즉 System.Threading.ReaderWriterLockSlim을 구현하는 것입니다. 이것에 대한 좋은 점은 모든 스레드가 동시에 읽을 수 있지만 쓰기의 모든 것을 차단할 수 있다는 것입니다. 그래서 본질적으로 당신은 글 쓰는 것을 막을뿐입니다. A는 ToList 또는 ToArray

void Main() 
{ 
    var slist = new List<Chunk>(); 
    var chunk = new Chunk{Name="asdf"}; 
    slist.Add(chunk); 
    var slist2 = slist.ToList(); 
    slist[0].Name = "asdf2"; 
    Console.WriteLine(slist[0].Name); // outputs: asdf2 
    Console.WriteLine(slist2[0].Name); // outputs: asdf2 
} 

public class Chunk 
{ 
    public string Name {get;set;} 
}