2013-07-27 4 views
0

지난 4 년 동안 C# 코드를 사용해 보았지만 최근에는 결코 통과하지 못하는 시나리오를 겪었습니다. "Index out of range error"문제를 해결하기위한 프로젝트가 있습니다. 코드가 미친 듯이 보이고 모든 불필요한 것들이 있었지만 지난 3 년 동안 생산 중이었기 때문에이 문제를 해결해야합니다. 문제가 발생했습니다. Parallel.Foreach에서 동기화 잠금 문제가 발생했습니다.

class FilterCondition 
{ 
    ..... 
    public string DataSetName {get; set;} 
    public bool IsFilterMatch() 
    { 
     //somecode here 
     Dataset dsDataSet = FilterDataSources.GetDataSource(DataSetName); // Static class and Static collection 
     var filter = "columnname filtername" 
     //some code here 
     ds.defaultview.filter= filter; 
     var isvalid = ds.defaultView.rowcount > 0? true : false; 
     return isValid; 
    } 
} 

// from a out side function they put this in a parallel loop 

Parallel.ForEach() 
{ 
    // at some point its calling 
    item.IsFiltermatch(); 
} 

내가 디버깅

, dsDataSet 나는 dsDataSet 내 여러 스레드를 수정 한 것을 보았다. 그래서 경쟁 조건이 발생하고 필터를 적용하지 못하고 범위를 벗어난 인덱스로 실패합니다.

내 질문은 여기 내 질문은, 내 방법은 비 정적 및 스레드 안전, 다음이 경쟁 조건이 발생하는 방법 dsDataset 내 멤버 함수 내에서 로컬 변수입니다. 이상하게도, 나는 Parallel과 관련이 있다고 생각합니다 .Foreach.

정상적인 잠금 장치를 놓았을 때 문제가 해결되었으므로 응답이 없습니다. 왜 비 정적 멤버 함수에 락을 두어야합니까?

누구든지 내게이 문제에 대한 답변을 줄 수 있습니까? 나는이 그룹에 처음 온 사람이다. 질문에 빠진 것이 있으면 알려주세요. 클라이언트 제한이 있기 때문에 전체 코드를 복사 할 수 없습니다. 읽어 주셔서 감사합니다.

+0

이 호출에 문제가 있습니다. FilterDataSources.GetDataSource (DataSetName); 당신은 공유되는 자원에 글을 쓰고 있습니다. 그리고 잠금을 구현해야합니다. – Ehsan

답변

2

스레드로부터 안전하지 않기 때문에.
여러 스레드에서 정적 컬렉션에 액세스하고 있습니다.

로컬 변수에 대한 오해가 있습니다. 변수는 지역 변수이지만, 그렇지 않은 객체를 가리키고 있습니다.

정적 컬렉션을 읽고 쓰는 장소 주변에 자물쇠를 추가하면됩니다.

+0

정적 리소스에 액세스하면 전체 메서드가 스레드를 안전하게 잃어 버릴 수 있습니까? 어때?정적 컬렉션이있는 경우 간단한 잠금이 문제를 해결하는 방법은 무엇입니까? 잠금 개체가 정적 정적이어야합니까? 심지어 나는 지역 변수에 대한 오해를 가지고 있습니다. – user2613883

+0

@ user2613883 스레드 안전은 메소드의 범위에 없습니다. 동일한 리소스에 액세스하는 것이 안전하다는 것입니다. 각 공유 자원에 대해 액세스를 동기화하려면 단일 잠금이 있어야합니다. 그래서 네, 자물쇠가 귀하의 경우에도 정적이어야하며, 모든 스레드가 동일한 잠금을 사용해야합니다. –

0

이 방법은 정적 메서드 인 것처럼 보이는 메서드 호출로도 FilterDataSources.GetDataSource(DataSetName)의 특정 (상태 비 저장, 스레드 안전하지 않은) 구현 때문에 발생한다고 생각합니다. 이 메서드는 캐시 된 데이터를 반환하는 다른 작업을 수행 할 수도 있습니다. DataSet 데이터 집합 항목에 대한 호출을 가로 채고 DataSet 래퍼를 반환하므로 데이터 집합이 아닌 래퍼로 작업하므로 많은 요소가있을 수 있습니다. "정확한 코드 행"을 사용하여 GetDataSource() 메서드와 모든 기본 정적 컨텍스트 FilterDataSource 클래스 (정적 필드, 생성자, 존재하는 경우 GetDataSource()에 의해 호출되는 다른 정적 메서드)의 구현을 보여 주도록하십시오. ..)

+0

고정 사전에서 데이터 집합을 가져 오는 중, 사전과 메소드 모두 정적입니다. – user2613883

1

문제 : 문제는 공유 자원에 작성하는이 방법 안에이 호출

FilterDataSources.GetDataSource(DataSetName); 

내에 자리 잡고 있습니다.

솔루션 :

현재 작성되고있는 필드 알고 그것을 잠금 구현해야 할 필요가있다.

참고 : 위의 방법으로 코드를 게시 할 수있는 경우보다 나은 위치에 있습니다.