코드 세부 사항 : 사전에있는 모든 서비스 개체에 대한 위의 코드에서병렬/멀티 스레드 싱글 톤 객체 메소드 호출
후속을 :입니다 발생
// Singleton class CollectionObject public class CollectionObject { private static CollectionObject instance = null; // GetInstance() is not called from multiple threads public static CollectionObject GetInstance() { if (CollectionObject.instance == null) CollectionObject.instance = new CollectionObject(); return CollectionObject.instance; } // Dictionary object contains Service ID (int) as key and Service object as the value // Dictionary is filled up during initiation, before the method call ReadServiceMatrix detailed underneath public Dictionary<int, Service> serviceCollectionDictionary = new Dictionary<int,Service>(); public Service GetServiceByIDFromDictionary(int servID) { if (this.serviceCollectionDictionary.ContainsKey(servID)) return this.serviceCollectionDictionary[servID]; else return null; } } DataTable serviceMatrix = new DataTable(); // Fill serviceMatrix data table from the database private int ReadServiceMatrix() { // Access the Singleton class object CollectionObject collectionObject = CollectionObject.GetInstance(); // Parallel processing of the data table rows Parallel.ForEach<DataRow>(serviceMatrix.AsEnumerable(), row => { //Access Service ID from the Data table string servIDStr = row["ServID"].ToString().Trim(); // Access other column details for each row of the data table string currLocIDStr = row["CurrLocId"].ToString().Trim(); string CurrLocLoadFlagStr = row["CurrLocLoadFlag"].ToString().Trim(); string nextLocIDStr = row["NextLocId"].ToString().Trim(); string nextLocBreakFlagStr = row["NextLocBreakFlag"].ToString().Trim(); string seqStr = row["Seq"].ToString().Trim(); int servID = Int32.Parse(servIDStr); int currLocID = Int32.Parse(currLocIDStr); int nextLocID = Int32.Parse(nextLocIDStr); bool nextLocBreakFlag = Int32.Parse(nextLocBreakFlagStr) > 0 ? true : false; bool currLocBreakFlag = Int32.Parse(CurrLocLoadFlagStr) > 0 ? true : false; int seq = Int32.Parse(seqStr); // Method call leading to the issue (definition in Collection Object class) // Fetch service object using the Service ID from the DB Service service = collectionObject.GetServiceByIDFromDictionary(servID); // Call a Service class method service.InitLanes.Add(new Service.LaneNode(currLoc.SequentialID, currLocBreakFlag, nextLoc.SequentialID, nextLocBreakFlag, seq)); }
문제를 메서드 호출이 이루어지지 않아 이후 처리에 문제가 발생합니다. 사전에 Service 객체를 병렬 모드로 가져 오는 작업을 수행해야합니다.
사전에 db가 모든 Ids/Service 객체를 포함하고 있지만, 필자의 이해는 Singleton 클래스의 병렬 모드에서 처리 할 때 몇 가지 객체 이 문제로 이끄는 것을 건너 뜁니다.
제 생각에는 전달 된 서비스 ID와 생성 된 서비스 개체가 로컬 스레드이므로 스레드가 문제가되지 않아야합니다. 이런 종류의 문제는 주어진 메소드 호출에 대해 하나의 쓰레드가 다른 쓰레드의 서비스 id 값을 쓰레드로 대체 할 때만 가능하다. 따라서 서비스 객체는 결국 서비스 객체로 끝나기 때문에 건너 뛰기는 거의 발생하지 않는다. 제대로
은 현재 내가
검토하십시오 foreach 루프를 사용하는 대신 Parallel.ForEach/Parallel.Invoke에 의해 비 스레드 모드에서 동일한 코드를 실행할 수 있어요이 경우 멀티 스레딩을 이해하지 문제를 해결하는 데 도움이되는 귀하의 견해 또는 모든 포인터를 알려주십시오.
감사 스콧에게, 두 개 이상의 스레드가 점점 실현하지 않았다 InitLanes는 사전에 정의 된 동일한 서비스 객체를 사용하므로 문제가 발생합니다. InitLanes는 비표준 모드에서 광범위하게 액세스되는 사용자 정의 데이터 구조이며, 스레드 안전하지 않은 목록으로 변환하는 것이 현명합니다. 현재 제안 된대로 lock 객체를 사용하고 있습니다. –
'InitLanes'은 클래스를 통과해야만 내부 상태가 엉망이되지 않도록 적절한 잠금을 수행해야하는 맞춤 데이터 구조입니다. ['ReaderWriterLock'] (http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlock%28v=vs.110%29.aspx)이 변환을 수행하는 데 큰 도움이 될 것입니다. 많은 독자가 동시에 모든 클래스에 액세스 할 수 있지만 한 명의 작가가있는 즉시 액세스를 차단하여 자물쇠가 잠금 장치가있는 위치가 아닌 다른 위치에 독자 또는 작성자가 액세스 할 수 없도록합니다 . –