2008-08-15 4 views
4

Google 팀에서 이전 채용 작업 흐름 시스템을 대신하여 새 채용 워크 플로 시스템을 만들고 있습니다. 이전 데이터를 새로운 스키마로 마이그레이션하는 임무가 주어졌습니다. 필자는 스키마가 근본적으로 다르고 스트레이트 TSQL 스크립트가 적절한 솔루션이 아니기 때문에 작은 Windows Forms 프로젝트를 만들어이 작업을 수행하기로 결정했습니다.Windows Forms 스레딩 및 이벤트 - ListBox 업데이트가 즉시 처리되지만 진행률 막대에 막대한 지연이 발생합니다.

작업은 다음 위임 이벤트 선언 않는 주요 봉인 클래스 'ImportController'

Thread dataProcessingThread = new Thread(new ParameterizedThreadStart(ImportController.ImportData)); 
dataProcessingThread.Name = "Data Importer: Data Processing Thread"; 
dataProcessingThread.Start(settings); 

:

public delegate void ImportProgressEventHandler(object sender, ImportProgressEventArgs e); 
public static event ImportProgressEventHandler importProgressEvent; 

메인 윈도우는 새로운 스레드를 사용하여 해당 클래스의 정적 메서드를 시작을 ImportProgressEvent args는 문자열 메시지, 진행률 막대의 최대 int 값 및 현재 진행 int 값을 전달합니다. 윈도우 폼 이벤트에 subcribes :

ImportController.importProgressEvent += new ImportController.ImportProgressEventHandler(ImportController_importProgressEvent); 

그리고 그것은 자신의 대리인의 사용이 방식으로 이벤트에 응답 : 마지막으로 진행률 표시 줄과 목록 상자가 업데이트됩니다

private delegate void TaskCompletedUIDelegate(string completedTask, int currentProgress, int progressMax); 

private void ImportController_importProgressEvent(object sender, ImportProgressEventArgs e) 
      { 
       this.Invoke(new TaskCompletedUIDelegate(this.DisplayCompletedTask), e.CompletedTask, e.CurrentProgress, e.ProgressMax); 
      } 

:

private void DisplayCompletedTask(string completedTask, int currentProgress, int progressMax) 
     { 
      string[] items = completedTask.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 

      foreach (string item in items) 
      { 
       this.lstTasks.Items.Add(item); 
      } 

      if (currentProgress >= 0 && progressMax > 0 && currentProgress <= progressMax) 
      { 
       this.ImportProgressBar.Maximum = progressMax; 
       this.ImportProgressBar.Value = currentProgress; 
      } 
     } 

ListBox가 매우 빠르게 업데이트되는 것처럼 보이지만 진행률 표시 줄은 배치가 거의 완료 될 때까지 결코 움직이지 않습니다 ??? 뭐라 구요?

답변

0

@ 존

감사합니다.

@Will 나는 그것이 오직 하나 개의 스레드를 생성합니다 알고 threadpooling 아무런 이득이 없다

. SQL Server가 읽기 및 쓰기로 두드려지는 동안 스레드를 사용하는 것은 순전히 응답 형 UI를 갖는 것입니다. 확실히 짧은 실재 스레드가 아닙니다.

썰매 망치에 관해서는 당신 말이 맞습니다. 그러나 결국 내 문제는 화면과 의자 사이에서 발생했습니다. 나는 다른 배치보다 많은 외래 키 레코드를 가진 많은 데이터를 가지고있는 것처럼 보이며, 프로세스 초기에 선택되어서 currentProgress가 좋은 10 초 동안 +++를 얻지 못한다는 것을 의미합니다.

@All, 그것은 나를 제가 아직 증명 겸손의 내 ahaa 순간을 주도 코드, 다른 곳에서 찾고있어 어떤 생각있어 모든 입력

다시 한번 감사 오류가 보통 사람입니다 :)

-1

당신은 UI 스레드가이 모든 과정에서 자유롭게 실행되고 있는지 확인 있습니까? 가입 또는 다른 대기 상태에서 막혀 있지 않습니다. 그것이 저에게 보이는 것입니다.

BackgroundWorker를 사용하는 것이 좋습니다. 이는 새로 고침/업데이트 호출이로드되면서 문제를 해결하는 것보다 낫습니다.

BackgroundWorker는 풀 스레드를 사용합니다. 풀 스레드는 자신의 수명이 짧은 스레드를 만드는 것보다 행동하기 쉬운 방법입니다.

0

상태 표시 줄 대화 상자에서 취소 버튼을 누를 때와 같이 GUI 입력을 사용자 입력에 반응 시키려면 범위 밖일 수도 있지만 때로는 유용합니다.

0

Windows Vista를 실행 하시겠습니까? 일부 작업 관련 응용 프로그램에서 정확히 똑같은 것으로 나타났습니다. 어떻게 든, 진행 막대가 "생기있는"때 지연이있는 것처럼 보입니다.

-1

는 나는 그것이 오직 하나 개 스레드를 생성 알고 로 threadpooling 아무런 이득이 없습니다. 스레드의 사용은 순응하는 UI를 갖는 이며, SQL 서버는 읽기로 두드리고 글을 쓰고 있습니다. 확실히 살아있는 스레드가 아닙니다.

확인해 주셔서 감사 드리며 귀하의 버그를 발견해 주셔서 감사합니다.하지만 BackgroundWorker를 보셨습니까? 그것은 당신이하고있는 일을 정확하게하지만, 표준화 된 방식으로 (즉, 자신의 델리게이트없이) 그리고 새로운 스레드를 만들지 않아도됩니다. 둘 다 (아마도 작지만 어쩌면 여전히 유용 할 것입니다) 이점이 있습니다.