2009-12-13 4 views
1

다음 두 가지 방법을 사용하고 있습니다. DoMyWork1이라는 메서드는 3 개의 스레드에서 3 개를 실행하는 데 6 초가 걸리는 것처럼 잘 확장됩니다. 반면 DoMyJob 메서드는 전혀 확장되지 않습니다. 하나의 쓰레드가 4 초 걸리면 3 개의 쓰레드를 실행하는데 13 초가 걸립니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까? 파일 읽기 및 쓰기에 스레드 풀 이외의 특별한 스레드 처리가 필요합니까?vs2008 C# : 스레드 풀 질문

내 호출 코드

public static void Process(MyDelegate md , int threads) 
{ 
    int threadcount = threads; 

    ManualResetEvent[] doneEvents = new ManualResetEvent[threadcount]; 

    DateTime dtstart = DateTime.Now; 

    List<string> myfiles = GetMyFiles(@"c:\"); 


    for (int i = 0; i < threadcount; i++) 
    { 

     doneEvents[i] = new ManualResetEvent(false); 
     MyState ms = new MyState(); 
     ms.ThreadIndex = i; 
     ms.EventDone = doneEvents[i]; 
     ms.files = myfiles; 
     ThreadPool.QueueUserWorkItem(md.Invoke, ms); 
    } 


    WaitHandle.WaitAll(doneEvents); 

    DateTime dtend = DateTime.Now; 
    TimeSpan ts = dtend - dtstart; 
    Console.WriteLine("All complete in {0} seconds.", ts.ToString()); 
    Console.ReadLine(); 

} 

public static void DoMyWork1(Object threadContext) 
{ 
    MyState st = (MyState)threadContext; 
    Console.WriteLine("thread {0} started...", st.ThreadIndex); 

    Thread.Sleep(5000); 

    Console.WriteLine("thread {0} finished...", st.ThreadIndex); 
    st.EventDone.Set(); 
} 



private static void DoMyJob(MyState st) 
{ 
    Console.WriteLine("I am in thread {0} started...", st.ThreadIndex); 


    string[] mystrings = new string[] { "one", "two", "three" }; 

    foreach (string s in mystrings) 
    { 
     foreach (string file in st.files) 
     { 
      if (!(new StreamReader(file).ReadToEnd().Contains(s))) 
      { 
       AppendToFile(String.Format("{0} word searching in file {1} in thread {2}", s, file, st.ThreadIndex)); 
      } 


     } 
    } 

    Console.WriteLine("I am in thread {0} ended...", st.ThreadIndex); 
} 
+0

스레드를 발송하는 데 사용하는 코드를 추가 할 수 있습니까? –

+0

공용 static void 프로세스 (MyDelegate md, int threads) { int threadcount = threads; ManualResetEvent [] doneEvents = new ManualResetEvent [threadcount]; DateTime dtstart = DateTime.지금; 목록 myfiles = GetMyFiles (@ "c : \"); (int i = 0; i

답변

2

스레드는 프로그램에서 CPU 리소스가 부족한 경우에만 프로그램 성능을 향상시킬 수 있습니다. 프로그램의 경우는 아니므로 Taskmgr.exe 성능 탭에서 쉽게 볼 수 있어야합니다. 여기서 느린 리소스는 하드 디스크 또는 네트워크 카드입니다. ReadToEnd() 호출은 디스크가 파일 데이터를 검색하기를 기다리는 동안 느리게 진행됩니다. 파일 데이터로 수행하는 작업은 그보다 3 배 이상 빠릅니다.

스레드는 디스크 데이터를 기다리지 만합니다. 사실 스레드가 실제로 프로그램을 훨씬 느리게 실행시킬 수있는 좋은 기회가 있습니다. 각 스레드가 다른 파일로 작업 중이기 때문에 디스크 드라이브 헤드가 디스크의 분리 된 트랙 사이에서 앞뒤로 건너 뛰게됩니다. 한 가지가 입니다. 속도가 느려 헤드가 다른 트랙을 찾고 있습니다. 일반적으로 빠른 디스크의 경우 약 10msec입니다. 약 50 만 CPU 명령어와 동일합니다.

더 빠른 디스크를 얻지 않으면 프로그램을 더 빠르게 실행할 수 없습니다. SSD가 좋습니다. 파일 시스템 캐시의 효과에주의하십시오. 프로그램을 두 번 실행하면 파일 데이터가 디스크 대신 캐시에서 검색 될 때 매우 빠르게 실행됩니다. 이것은 프로덕션 환경에서 거의 발생하지 않습니다.

0

모든 파일 액세스는 OS 층에서 시리얼 될 것 등으로 스레딩 당신이 볼을 정확히 될 것입니다.

+0

거기에 멀티 스레드 파일 처리 방법이 있습니까 ?? –

+0

이 컨텍스트에서 '직렬'로 무엇을 의미하는지 정확히 알지는 못했지만 올바른지 (파일 액세스는 계속됩니다) 믿을 수 없습니다. 물론 파일 IO를 동시에 수행하는 두 개의 스레드를 가질 수 있습니다. 당연히 디스크의 헤드는 한 번에 플래터의 한 부분에만있을 수 있지만 하드웨어 및 OS는 일반적으로 문제가되지 않도록 유지 보수 작업을 수행합니다. – Bruce

+0

http://stackoverflow.com/questions/93834/when-is-multi-threading-not-a-good-idea http://objectmix.com/smalltalk/761155-multi-threaded-file-access.html 이것은 내 출처였습니다. , yspi –

0

나는 조금 놀랐다. 나는이 파일에 대한 첫 번째 액세스가 캐시에 저장 될 것으로 예상하고 나머지 액세스는 메모리에 도달 할 것으로 기대한다. 그래서 세 개의 쓰레드는 하나보다 너무 느려서는 안됩니다. 각 파일에 쓰는 경우 차이가 있습니다. 정확히 AppendToFile 함수는 무엇을합니까?

0

찾고있는 각각의 새 문자열에 대해 각 파일을 열고 읽는 것이 하나의 문제 일 수 있습니다.

foreach 루프의 순서를 바꾸고 필요에 따라 파일에 추가하는 경우 어떻게됩니까?

더 나은 성능을 기대합니다.

이상적으로 루프에서 파일을 읽을 수 있다면 가장 빠릅니다. I/O 바운드 작업은 항상 디스크에서 데이터를 반환하기 위해 대기하는 컨텍스트 스위치를 발생시킵니다.