홈>
ConcurrentDictionary를 사용하여 레코드를 보유하고 있습니다. 프로세스 속도를 높이기 위해 로컬 시스템에서 파일을 병렬로 읽고 있습니다.
샘플 1 :
static ConcurrentDictionary<Int64, Byte[]> concurrentDictionary = new ConcurrentDictionary<Int64, Byte[]>();
private void ReadFilesFromDirectory()
{
string[] docNames = Directory.GetFiles(CompleteLettersDirectory);
Parallel.ForEach(docNames, new ParallelOptions { MaxDegreeOfParallelism = 8 }, file =>
{
try
{
int64 letterId = Convert.ToInt64(file.Split('_')[1]);
Byte[] CompleteLetterContent;
CompleteLetterContent = ConvertToPdfWithAspose(System.IO.File.ReadAllBytes(file), letterId);
concurrentDictionary.GetOrAdd(letterId, CompleteLetterContent);
}
catch (Exception ex)
{
//Logger.WriteFile(letterId.ToString() + Environment.NewLine, ex);
}
}
}
샘플 2 :이 샘플에서는 여러 속성을 가진 문자 클래스를 만들었으므로 여러 값을 사전에 유지하려고합니다.
Letter
로
클래스는 스레드로부터 안전하지 않습니다. 문제가 발생합니까?
static ConcurrentDictionary<Int64, Letter> concurrentDictionary = new ConcurrentDictionary<Int64, Letter>();
private void ReadFilesFromDirectory()
{
string[] docNames = Directory.GetFiles(CompleteLettersDirectory);
Parallel.ForEach(docNames, new ParallelOptions { MaxDegreeOfParallelism = 8 }, file =>
{
try
{
int64 letterId = Convert.ToInt64(file.Split('_')[1]);
Byte[] LetterContent;
Byte[] CompleteLetter;
Letter letter = new Letter();
letter.LetterId = letterId;
if(file.Contains("CL"))
{
letter.CompleteLetter = ConvertToPdfWithAspose(System.IO.File.ReadAllBytes(file), letterId);
}
else
{
letter.LetterContent = ConvertToHTML(System.IO.File.ReadAllBytes(file), letterId);
}
concurrentDictionary.GetOrAdd(letterId, letter);
}
catch (Exception ex)
{
//Logger.WriteFile(letterId.ToString() + Environment.NewLine, ex);
}
}
}
public class Letter
{
public Int64 LetterId { get; set; }
public Byte[] LetterContent { get; set; }
public Byte[] CompleteLetter { get; set; }
}
모든 사람이 코드 샘플이 스레드 안전인지 조언 할 수 있습니까?
또한 문자열
docNames
디렉토리에서 문서를 보유하고
Parallel.ForEach
로 전달됩니다.
스레드 안전합니까? 또는 다른 권장 사항.
- 답변 # 1
- 답변 # 2
"스레드 세이프"라는 용어는 일반적으로 멤버 함수가 다른 스레드에서 호출 될 때 객체의 동작을 나타냅니다. 그것은
ConvertToHTML
를 의미 클래스는 스레드 안전하거나 스레드 안전이 아닌 것으로 설명하기에는 너무 간단합니다. 일부 공용 멤버가있는 바보 같은 클래스 일뿐입니다. 다른 필드에 쓰는 데 문제가 없으며 동일한 필드에 쓰는 것조차 잘못 될 수 있습니다. 하나의 값이 손실되지만 무엇을 기대 했습니까? 그러나 Letter와 ConcurrentDictionary를 결합하는 방식은 거꾸로됩니다. 다음과 같은 작업을 수행해야합니다.Letter
코드에서 키가 존재하면 새로 만든 문자 (및 저장된 데이터)가 바닥에 떨어집니다.
var letter = concurrentDictionary.GetOrAdd(letterId, new Letter()); if(file.Contains("CL")) { letter.CompleteLetter = ConvertToPdfWithAspose(System.IO.File.ReadAllBytes(file), letterId); } else { letter.LetterContent = ConvertToHTML(System.IO.File.ReadAllBytes(file), letterId); }
의 사용 괜찮습니다.docNames
관련 질문
- c# : 다른 스레드를 기다리는 동안 Application.DoEvents
- c# : 다음 '스레드 안전 이중 확인 지연 초기화' 패턴을 사용해도 괜찮습니까?
- c# : Parallel.For에서 ArgumentOutOfRangeException이 발생합니다.
- c# : EF 업데이트 대기는 이전 작업 시간이 초과된 경우 지원되지 않는 MultipleActiveResultSets 예외를 throw합니다.
- c# : 작업 내부에서 정적 메서드 호출
- c# : 스레드로부터 안전한 WebApi 넣기 요청
- c# : 비동기 병렬 루프 내부의 ForEach 루프
- C# .Net Core에서 다른 REST API 요청을 병렬로 실행하는 방법은 무엇입니까?
- c# : Monitor.Pulse(All) 다음 Monitor.Wait()
와이즈 비즈
실제로 유익한가요? 하드 디스크는 동시 요청을 충족시키기 위해 앞뒤로 이동해야 할 때가 아니라 순서대로 읽을 때 가장 잘 작동합니다. (그리고 SSD가 있어도 아무것도 얻지 못할 것입니다.)
<시간>유형에 프레임 워크 이름을 사용하는 습관이있는 것 같습니다 (예 :
Byte
) 대신 C # 이름 (Int64
)byte
). C # 이름을 사용하는 것이 더 일반적이라고 생각합니다. <시간>여기서 선언과 과제를 분리 할 이유가 없습니다. 또한 지역 변수는 일반적으로 camelCase로 작성됩니다.
<시간>당신은 이미
<시간> 당신은System.IO.File.ReadAllBytes(file)
입니다 네임 스페이스는 여기서 중복되어야합니다.using System.IO
라는 다른 것이 있기 때문에 그렇지 않다면 그런 다음 해당 충돌을 해결해야합니다.concurrentDictionary.GetOrAdd(letterId, CompleteLetterContent);
를 호출 하지만 항상 추가하고 싶고 결코 원하지 않습니다. 이를 위해GetOrAdd()
를 사용할 수 있습니다 또는 인덱서 세터 :세 가지 경우 모두 같은 키를 가진 값이 없으면 동작은 동일하지만 후자의 두 가지가 더 명확하다고 생각합니다.
<시간>이 변수는 사용되지 않습니다. 제거하십시오.
<시간>Letter letter = new Letter(); letter.LetterId = letterId;
를 사용할 수 있습니다 (지정에서 유형이 명확하지 않기 때문에) 및 객체 이니셜 라이저 :두 지점에서 모두
<시간>if(file.Contains("CL")) { letter.CompleteLetter = ConvertToPdfWithAspose(System.IO.File.ReadAllBytes(file), letterId); } else { letter.LetterContent = ConvertToHTML(System.IO.File.ReadAllBytes(file), letterId); }
를 반복하고 있습니다. 부품. 조건 전에 지역 변수로 추출하는 것을 고려하십시오.표시 한 코드는 호출하는 메소드 (
System.IO.File.ReadAllBytes(file)
)를 가정 할 때 스레드에 안전한 것으로 보입니다.ConvertToPdfWithAspose
)는 스레드로부터 안전합니다.