2012-07-30 5 views
0

시간이 많이 걸리는 루틴 중 하나를 호출 할 때마다 팝업을 표시하고 진행률 표시 줄을 표시하는 양식을 만들었습니다. UpdateProgress 방법을 통해 일상의 진행 상황을 알려줍니다.백그라운드 작업자 작업자가 완료된 후 ProgressChanged 작업

저는이 양식이 업데이트되는 동안 사용자가 양식을 옮기고 사업을 계속할 수 있도록하기 위해 배경 작업자를 사용하고 있습니다. 그러나 양식은 루틴이 완료 될 때까지 잠그고 진행률 막대를 100 %로 빠르게 올리고 종료해야합니다. 진행률 표시 줄은 UpdateProgress 메소드에 대한 호출 진행 상황과 함께 업데이트됩니다.

내가 뭘 잘못하고 있니?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Threading; 

namespace myNameSpace 
{ 
    public partial class ProgressIndicator : Form 
    { 
     int progressPercentage; 

     public ProgressIndicator() 
     { 
      InitializeComponent(); 
     } 

     void progressUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      // update the UI with appropriate fields 
      progressBar.Value = e.ProgressPercentage; 
      labelCommunicating.Text = "In progress: " + e.ProgressPercentage + "% complete"; 
     } 

     void progressUpdater_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      this.Close(); 
     } 

     void progressUpdater_DoWork(object sender, DoWorkEventArgs e) 
     { 
      BackgroundWorker worker = sender as BackgroundWorker; 

      while (true) 
      { 
       if (progressPercentage >= 100) 
       { 
        break; 
       } 

       worker.ReportProgress(progressPercentage); 

       Thread.Sleep(100); 
      } 
     } 

     public void UpdateProgress(int progressPercentage) 
     { 
      this.progressPercentage = progressPercentage; 
     } 

     private void ProgressIndicator_Load(object sender, EventArgs e) 
     { 
      BackgroundWorker progressUpdater = new BackgroundWorker(); 
      progressUpdater.WorkerReportsProgress = true; 
      progressUpdater.WorkerSupportsCancellation = true; 
      progressUpdater.DoWork += new DoWorkEventHandler(progressUpdater_DoWork); 
      progressUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(progressUpdater_RunWorkerCompleted); 
      progressUpdater.ProgressChanged += new ProgressChangedEventHandler(progressUpdater_ProgressChanged); 

      progressUpdater.RunWorkerAsync(); 
     } 
    } 
} 
+1

게시 한 코드로 문제를 재현 할 수있는 방법이 없습니다. DoWork에서 Sleep()을 사용하면 항상 문제를 숨 깁니다. 그러나 실제 DoWork 이벤트 처리기는 종종 ReportProgress를 너무 자주 호출합니다. UI 스레드가 빠르면 빠를 수 있습니다. 뒤쳐지기 시작합니다. 수시로 전화를 걸면 우선 순위가 낮은 임무를 수행하지 않습니다. 사용자 입력에 응답하거나 컨트롤을 페인팅하는 것과 같습니다. 그것은 죽어 보일 것이다. 인간은 UI 스레드를 넘치게하는 것보다 적은 * 초당 25 번 속도로 진행률을 볼 수 있습니다. –

+0

어? "작업"(DoWork 핸들러)을 수행 할 때 진행 상황을 전혀 업데이트하지 않습니다. 또한 UpdateProgress가 호출되는 방식의 예는 표시하지 않습니다. 일반적으로 "진행"은 완료된 작업의 표시입니다. 이는 DoWork 핸들러가 수행하는 작업입니다. –

+0

Hans : 응용 프로그램이 자원을 낭비하지 않도록 sleep이 추가되었습니다. 피터 : 작업은 다른 곳에서 수행됩니다. 여기서 'DoWork'방법은 진행 상황을 확인하고 이에 따라 화면을 업데이트하는 것입니다. 진행은'UpdateProgress' 메소드에서 변경됩니다. – Kashif

답변

1

이것은 멀리 가져온 솔루션처럼 냄새가 나는데 문제는 while loop입니다. 그러나 더 좋은 방법은 Invoke();을 사용하여 UI를 차단하지 않고 ProgressBar을 업데이트하는 것입니다.

+0

답변 해 주셔서 감사합니다. 이것은 내가하려고하는 것보다 훨씬 좋아 보인다. 'updateProgress'라고하는 첫 줄에 오류가 나타납니다. 'updateProgress'가 현재 컨텍스트에 존재하지 않는다고 말합니다. – Kashif

+0

약간의 오류가 있었지만 지금 업데이트되었습니다. 모든 메서드와 대리자 및 호출이 진행 상황을 업데이트하는 양식 클래스 내에 있는지 확인하십시오. –

+0

다른 클래스의 전화를 걸고 있습니다. 이렇게하려면 코드를 어떻게 올바르게 만들 수 있습니까? – Kashif

0

Invoke 메서드를 사용하여 호출을 래핑 할 필요가없는 방식으로 프로세스를 만들 수 있습니다.

//delegate method 
private delegate void updateProgressDelegate(int progress); 

//actual method 
private void updateProgress(int progress) 
{ 
    if(this.InvokeRequired) 
    { 
     this.Invoke(new updateProgressDelegate(updateProgress), progress); 
    } 
    else 
    { 
     progressBar.value = progress; 
    } 
} 
관련 문제