2010-08-16 9 views
1

나는 이미 작업을 시작한 응용 프로그램을 가지고 있으며 약간의 것들을 재고 할 필요가있는 것으로 보인다. 응용 프로그램은 현재 winform 응용 프로그램입니다. 어쨌든, 사용자가 실행하고 싶은 스레드 수를 입력 할 수 있도록 허용합니다. 또한 사용자가 스레드 당 처리 할 레코드 수를 할당 할 수도 있습니다. 내가 한 일은 가변 수의 쓰레드를 반복하고 이에 따라 쓰레드를 생성하는 것입니다. 스레드에서 잠금을 수행하지 않고 있는지 여부를 확인할 필요가 없습니다. 나는 스레딩에 익숙하지 않고 여러 코어를 가지고 가능한 문제를 겪고 있습니다. 이 기능을 더 잘 수행 할 수있는 방법에 대한 조언이 필요합니다..NET 다중 스레드 도움말

스레드가 생성되기 전에 일부 레코드가 내 데이터베이스에서 처리되어 처리됩니다. 해당 목록 개체는 스레드로 보내지고 반복됩니다. 루프의 끝 부분에 도달하면 스레드는 데이터 함수를 호출하여 새로운 레코드를 가져 와서 목록에서 이전 레코드를 대체합니다. 더 이상의 레코드가 없어 질 때까지 계속됩니다. 여기 내 코드는 다음과 같습니다

private void CreateThreads() 
{ 
    _startTime = DateTime.Now; 
    var totalThreads = 0; 
    var totalRecords = 0; 
    progressThreadsCreated.Maximum = _threadCount; 
    progressThreadsCreated.Step = 1; 
    LabelThreadsCreated.Text = "0/" + _threadCount.ToString(); 
    this.Update(); 
    for(var i = 1; i <= _threadCount; i++) 
    { 
     LabelThreadsCreated.Text = i + "/" + _threadCount; 
     progressThreadsCreated.Value = i; 
     var adapter = new Dystopia.DataAdapter(); 
     var records = adapter.FindAllWithLocking(_recordsPerThread,_validationId,_validationDateTime); 
     if(records != null && records.Count > 0) 
     { 
      totalThreads += 1; 
      LabelTotalProcesses.Text = "Total Processes Created: " + totalThreads.ToString(); 




      var paramss = new ArrayList { i, records }; 
      var thread = new Thread(new ParameterizedThreadStart(ThreadWorker)); 
      thread.Start(paramss); 
     } 

     this.Update(); 
    } 


} 


private void ThreadWorker(object paramList) 
{ 
    try 
    { 
     var parms = (ArrayList) paramList; 
     var stopThread = false; 
     var threadCount = (int) parms[0]; 
     var records = (List<Candidates>) parms[1]; 
     var runOnce = false; 
     var adapter = new Dystopia.DataAdapter(); 
     var lastCount = records.Count; 
     var runningCount = 0; 
     while (_stopThreads == false) 
     { 
      if (!runOnce) 
      { 
       CreateProgressArea(threadCount, records.Count); 
      } 
      else 
      { 
       ResetProgressBarMethod(threadCount, records.Count); 
      } 


      runOnce = true; 
      var counter = 0; 
      if (records.Count > 0) 
      { 
       foreach (var record in records) 
       { 
        counter += 1; 
        runningCount += 1; 
        _totalRecords += 1; 
        var rec = record; 
        var proc = new ProcRecords(); 
        proc.Validate(ref rec); 

        adapter.Update(rec); 

        UpdateProgressBarMethod(threadCount, counter, emails.Count, runningCount); 

        if (_stopThreads) 
        { 
         break; 
        } 
       } 

       UpdateProgressBarMethod(threadCount, -1, lastCount, runningCount); 

       if (!_noRecordsInPool) 
       { 
        records = adapter.FindAllWithLocking(_recordsPerThread, _validationId, _validationDateTime); 
        if (records == null || records.Count <= 0) 
        { 
         _noRecordsInPool = true; 
         break; 
        } 
        else 
        { 
         lastCount = records.Count; 
        } 
       } 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 
+0

당신이 겪고있는 문제는 무엇입니까? 또한 MessageBox.Show를 catch하는 예외에서 UI 스레드를 발생시켜야한다고 확신합니다. 귀하의 진행률 표시 줄이 당신이 이미이 일을하고 있는지 추측하고 있지만 여기에 아이디어에 대한 참조 질문이 있습니다 (http://stackoverflow.com/questions/2367718/c-automating-the-invokerequired-code-pattern). 이것 때문에 예외를 잃어 가고있는 것일까 요? –

+0

대리자를 사용하여 UI를 업데이트하고 있습니다. 그건 잘 작동합니다. 그래도 의견에 감사드립니다. – DDiVita

답변

3

을 실행하고 싶은 스레드의 수는 입니다. 또한 사용자가 에 스레드 수 당 개의 레코드 수를 할당하도록 허용합니다.

이것은 사용자에게 실제로 공개하고 싶은 것이 아닙니다. 그들이 무엇을 넣어야 하는가? 그들은 무엇이 최선인지를 어떻게 결정할 수 있습니까? CLR 또는 다른 라이브러리에서 가장 잘 구현 된 구현 세부 사항입니다.

내가 어떤 잠금을 수행하고 있지 않다 (그리고 내가 필요 여부를 확실하지 )를 스레드.

대부분의 멀티 스레딩 문제는 공유 상태에서 발생합니다. 특히 ThreadWorker 방법에서는 _stopThreads, _totalRecords, _noRecordsInPool, _recordsPerThread, _validationId_validationDateTime과 같은 공유 데이터를 참조하는 것으로 보입니다.

그러나 이러한 데이터가 공유 되었기 때문에 문제가있는 것은 아닙니다. 그것은 모두 누가 그것을 읽고 쓰는지에 달려 있습니다. 예를 들어, _recordsPerThread은 처음에는 한 번 작성된 다음 모든 스레드에서 읽을 수 있다고 생각합니다. 그러나 _totalRecords은 각 스레드에서 읽고 쓰게됩니다._totalRecords += 1;은 non-atomic read-then-write로 구성되어 있기 때문에 여기에서 스레딩 문제를 해결할 수 있습니다. 즉, 두 스레드가 _totalRecords의 값을 읽은 다음 (둘 다 값 5를 읽은 다음) 복사본을 증가시키고 다시 쓰기를 할 수 있습니다. 그들은 모두 값 6을 다시 쓸 것이고, 이것은 7이어야하기 때문에 올바르지 않습니다. 이것은 고전적인 race condition입니다. 이 특별한 경우에는 Interlocked.Increment을 사용하여 필드를 원자 적으로 업데이트 할 수 있습니다.

일반적으로 C#의 스레드 간 동기화를 수행하려면 System.Threading 네임 스페이스의 클래스를 사용할 수 있습니다. Mutex, Semaphore 및 가장 일반적으로는 Monitor (lock과 동일)을 사용하면 한 번에 하나의 스레드 만 코드의 특정 부분을 실행할 수 있습니다. 동기화하는 데 사용하는 메커니즘은 전적으로 귀하의 성능 요구 사항에 달려 있습니다. 예를 들어, ThreadWorker 본체에 lock을 던지면 작업을 효과적으로 직렬화하여 멀티 스레딩을 통해 얻은 성능상의 이점을 모두 잃게됩니다. 안전하지만, 느린 :(당신이 Interlocked.Increment을 사용하고 신중하게 다른 동기화를 추가 할 경우 입수하면 다른 한편으로는, 필요, 당신이 올바른 :

될 것입니다 성능 당신의 응용 프로그램을 유지하는 것입니다 당신의 노동자 메서드를 스레드로부터 안전하게 보호하려면 스레드를 관리하는 다른 메커니즘을 사용해야합니다. ThreadPool이 언급되었고 ThreadPool을 초월하여 사용할 스레드 수를 현명하게 결정하고 조정하는 Task Parallel Library을 사용할 수도 있습니다. 이렇게하면 사용자가 부담해야하는 매직 스레드 수를 결정할 수 있습니다.

0

확실한 대답은 당신이 처음에 스레드를 원하는 이유를 질문하는 것입니다? 스레드를 사용하는 것이 이점이된다는 것을 보여주는 분석 및 벤치 마크는 어디에 있습니까?

비 GUI 스레드가 GUI와 상호 작용하지 않도록하려면 어떻게해야합니까? 어떻게 두 스레드가 같은 변수 나 데이터 구조와 안전하지 않은 방식으로 상호 작용하지 않도록 보장하고 있습니까? 잠금을 사용해야하는 경우에도 잠금 장치로 인해 각 스레드가 워크로드를 순차적으로 처리하지 않도록 보장하여 다중 스레드에서 제공 한 이점을 제거하는 방법은 무엇입니까?

+0

우리는 레코드의 유효성을 검사하고 해당 데이터의 유효성을 검사하는 네트워크 연결을 만들기 때문에 여러 스레드가 필요합니다. 우리는 데이터베이스에있는 수백만 개의 레코드를 다루고 있으며이를 수행 할 수있는 프로세스가 하나만 있으면 의사처럼 보이지 않습니다. 우리는 단지 하나의 쓰레드를 사용하려고했지만 프로세스가 너무 느렸다. – DDiVita

+1

소리가 극단적으로 내게 들립니다. (데이터의 유효성을 확인하기위한 연결 만들기) 쓰레드가 실제로 그 설명만으로 무엇인가를 얻는 것은 의심 스럽다. – Arafangion

+0

이 상황이 있습니다. 감사합니다 – DDiVita

4

여러분이 할 수있는 일은 간단합니다. perf 작성을 향상 시키려면 ThreadPool을 사용하여 스레드 생성을 관리해야합니다. 이것은 OS가 쓰레드를 지불하는 쓰레드 그룹을 할당하는 것이 여러 번 대신 페널티를 생성하는 것을 허용한다.

.NET 4.0으로 이동하려면 Task 가야합니다.

+0

안녕하세요, 여기에 반갑습니다 :) –

+0

질문에 대한 답변이 거의 없습니다 - 질문은 스레드 풀을 관리하거나 스레드 수를 최적화하는 방법에 대해 묻지 않습니다. 스레드를 처음 사용하는 방법. 사람들은 스레드 풀에 대해 알게 된 다음 잠금 및 다중 스레드 설계의 다른 기본적인 측면에 대해 알게되었습니다. (그것은 도구입니다, 다른 말로하면). – Arafangion

+0

사실 나는 그의 질문에 대답했다. 아주 정확하게. 그는 "내가 어떻게 이것을 더 잘 수행 할 수 있는지 물었다." Threads에 대한 깊은 이해가 중요하다는 점에 대해서는 정확하지만 ThreadPool은 성능을 향상시킵니다. – linuxuser27