>

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

    와이즈 비즈

    실제로 유익한가요? 하드 디스크는 동시 요청을 충족시키기 위해 앞뒤로 이동해야 할 때가 아니라 순서대로 읽을 때 가장 잘 작동합니다. (그리고 SSD가 있어도 아무것도 얻지 못할 것입니다.)

    <시간>

    유형에 프레임 워크 이름을 사용하는 습관이있는 것 같습니다 (예 :

    I'm reading files from the local system in parallel, to speed up the process.

    Byte ) 대신 C # 이름 ( Int64 ) byte ). C # 이름을 사용하는 것이 더 일반적이라고 생각합니다.

    <시간>

    long
    
    

    여기서 선언과 과제를 분리 할 이유가 없습니다. 또한 지역 변수는 일반적으로 camelCase로 작성됩니다.

    Byte[] CompleteLetterContent;
    CompleteLetterContent = ConvertToPdfWithAspose(System.IO.File.ReadAllBytes(file), letterId);
    
    

    <시간>

    Byte[] completeLetterContent = ConvertToPdfWithAspose(System.IO.File.ReadAllBytes(file), letterId);
    
    

    당신은 이미 System.IO.File.ReadAllBytes(file) 입니다 네임 스페이스는 여기서 중복되어야합니다. using System.IO 라는 다른 것이 있기 때문에 그렇지 않다면 그런 다음 해당 충돌을 해결해야합니다.

    <시간>

    File
    
    

    당신은 concurrentDictionary.GetOrAdd(letterId, CompleteLetterContent); 를 호출 하지만 항상 추가하고 싶고 결코 원하지 않습니다. 이를 위해 GetOrAdd() 를 사용할 수 있습니다  또는 인덱서 세터 :

    TryAdd()
    
    

    세 가지 경우 모두 같은 키를 가진 값이 없으면 동작은 동일하지만 후자의 두 가지가 더 명확하다고 생각합니다.

    <시간>

    concurrentDictionary.TryAdd(letterId, CompleteLetterContent);
    concurrentDictionary[letterId] = CompleteLetterContent;
    
    

    이 변수는 사용되지 않습니다. 제거하십시오.

    <시간>

         Byte[] LetterContent;
          Byte[] CompleteLetter;
    
    

    Letter letter = new Letter(); letter.LetterId = letterId; 를 사용할 수 있습니다  (지정에서 유형이 명확하지 않기 때문에) 및 객체 이니셜 라이저 :

    var
    
    

    <시간>

    var letter = new 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 )는 스레드로부터 안전합니다.

  • 답변 # 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

  • 이전 Y 케이블 또는 이중 전원 케이블을 사용하여 단일 USB 전원 하드 드라이브에 추가 전원을 공급할 수 있습니까?
  • 다음 표준 GPIO 핀으로 릴레이 채널의 16 개 채널 중 10 개를 구동 할 수 있습니까