2011-04-25 2 views
3

안녕하세요, 저는 작업 중 하나가 Excel을 변환하고 모든 레코드를 DB로 전달하는 응용 프로그램이 있습니다.WPF에서 ProgressBar와 함께 BackgroundWorker 사용

DB에 들어가서 삽입 할 행 수가 7000 개를 초과하므로 약간의 시간이 걸립니다.

이 작업에 3 분 이상 시간이 걸리기 때문에 ProgressBar를 사용하여이 작업의 진행 상태를보고 싶습니다.

내가 만든 클래스에서이 직업을하고 있다면, 어떻게하면 backgroundWorker를 사용하여 내 경우에 progessBar로 진행 상황을보고 할 수 있습니까?

내 목표는 진행 상황에 대한 백분율로 정확하며 진행 상황을보고하는 데이 모든 것을 어떻게 사용할 수 있습니까? 나는 backgroundWorkers로 일한 적이 없다.

나는 생각한다. 그리고 이것은 팁 일 수도 있고, 좋을 수도 있고 아닐 수도있다. 우선 Excel에서 행의 수를 얻고, 그 수를 ProgressBar의 Maxvalue로 만든 다음, 각 Row 또는 간격으로 만든다. 진행 상황을보고합니다.

이것은 가능합니까? 내가 어떻게 해?

답변

4

나는 ProgressBars에 대한 바인딩을 사용하고 (가능하면 다른 모든 것들), dispatching to the UI thread에 대해 걱정할 필요가 없기 때문에 바인딩을 사용하고 싶습니다.

기본적으로 ProgressBar를 바인딩 할 수있는 progress 속성을 사용하여 INotifyPropertyChanged을 구현하는 클래스를 만듭니다. 예 :

public class Task : INotifyPropertyChanged 
{ 
    private int _progress = 0; 
    public int Progress 
    { 
     get { return _progress; } 
     private set 
     { 
      if (_progress != value) 
      { 
       _progress = value; 
       OnPropertyChanged("Progress"); 
      } 
     } 
    } 

    public Task(ref ProgressChangedEventHandler progressChangedEvent) 
    { 
     progressChangedEvent += (s, e) => Progress = e.ProgressPercentage; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

이 클래스가 발생하는 경우 작업의 진행 상황을 업데이트합니다 생성자에서 이벤트를 사용하지만 당신은 당신이 원하는 방식으로, 예를 들어,에서 진행 변화를 처리 할 수 ​​있습니다 메서드를 사용하거나 Progress 속성을 public으로 변경하여 임의로 변경할 수 있습니다.


사용 예 :

<ProgressBar Minimum="0" Maximum="100" Height="20" 
      Value="{Binding UpdateTask.Progress, Mode=OneWay}"/> 
// The event that should be raised when a progress occurs. 
private event ProgressChangedEventHandler UpdateProgressChanged; 

// The task the ProgressBar binds to. 
private readonly Task _updateTask; 
public Task UpdateTask 
{ 
    get { return _updateTask; } 
} 

public MainWindow() 
{ 
    // Instatiate task, hooking it up to the update event. 
    _updateTask = new Task(ref UpdateProgressChanged); 
} 

private void OnUpdateProgressChanged(int progressPercentage) 
{ 
    if (UpdateProgressChanged != null) 
    { 
     UpdateProgressChanged(this, new ProgressChangedEventArgs(progressPercentage, null)); 
    } 
} 

// Simple progress simulation 
private void Button1_Click(object sender, RoutedEventArgs e) 
{ 
    int progress = 0; 
    DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(0.5) }; 
    timer.Tick += (sSub,eSub) => 
    { 
     progress++; 
     // Raise progress changed event which in turn will change 
     // the progress of the task which in turn will cause 
     // the binding to update which in turn causes the value 
     // of the ProgressBar to change. 
     OnUpdateProgressChanged(progress); 
     if (progress == 100) 
     { 
      timer.Stop(); 
     } 
    }; 
    timer.Start(); 
} 
+0

그래, 내가 진행 상황을 진행 상태에 바인딩하고 싶다면 Progress 속성을 사용 하시겠습니까? 진행률 표시 줄을이 속성에 바인딩하는 예를 들려 줄 수 있습니까? – Miguel

+0

예제를 추가하고 작업 클래스에 오류가 수정되면 비용 생성자는 이벤트를 참조 ('ref' 키워드)해야합니다. –

+0

어떤 이유인지 ProgressBar가 값을 업데이트하지 않습니다 ... – Miguel

0

다음은 background worker with progress의 예입니다.

그러나 상황에 따라 BGW가 작동하는지 다시 확인하십시오. COM interop을 통해 Excel을 제어하는 ​​경우 STA 스레드가 필요하며 BGW는 STA가 아닌 MTA 스레드입니다.

그런 경우가 있다면, 당신은 STA scheduler으로 Task를 사용할 필요가, 또는 수 있습니다 자신의 매뉴얼 Thread (I 강하게 Task 기반 접근 방식을 제안한다).

+1

예 내가 컴 Interop를 사용하고 있습니다. 그래서 당신이 말하는 작업 접근법은 진행자 링크를 가진 backgroudn worker에서 언급 된 것입니다. – Miguel

+0

예, 링크 된'StaTaskScheduler'를 사용해야합니다. –

관련 문제