2011-01-21 11 views
1

こんにちは バックグラウンドワーカーをプログレスバーに統合しようとしていますが、それを正しく取得できません。BackgroundWorker progressBar - 別のクラスでループが発生したときにReportProgressを実装する際の問題

私はいくつかのファイルを処理しており、すべての処理は外部クラスで行われています。

私の難しさは、通常、私がバックグラウンドワーカーと話しているこのクラスの中にループがあることです。

良いことは、ファイルを処理するときに、各ファイルが処理を完了するたびにイベントが発生することです。

これは、これがその場合

BackgroundWorker _bw = new BackgroundWorker 

    private void RunLongProcess() 
    { 
     _bw.WorkerReportsProgress = true; 
     _bw.WorkerSupportsCancellation = true;   
     _bw.DoWork += DoWork; 
     _bw.ProgressChanged += ProgressChanged; 
     _bw.RunWorkerCompleted += RunWorkerCompleted; 

     _bw.RunWorkerAsync();//start the process 

     if (_bw.IsBusy) 
      _bw.CancelAsync(); 
    } 

    static void DoWork (object sender, DoWorkEventArgs e) 
     {  

     var files=GetFiles(); 
     int fileCount=files.Count; 

     //usually I do a loop here but all the processing is done inside this class so 

     var fileProcessor=new FileProcesser(); 
     fileProcessor.ProcessFiles(files);   

     } 
    private void OnFileProcessCompleted(object sender, FileEventArgs e) 
    { 
     //Event Fired when a file has been processed 
     //How do I update progressBar.Problem cross threading here. 

         //What do I do here????? 
     _bw.ReportProgress(e.FileProcessedCount, e); 
    } 

    ProgressChanged (object sender, ProgressChangedEventArgs e) 
    { 
      // Update the UI 
     labelProgress.Text = e.UserState; 
     progressBar.Value = e.ProgressPercentage; 
    } 


    private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (e.Cancelled) 
      // Console.WriteLine("You canceled!"); 
     else if (e.Error != null) 
      //Console.WriteLine("Worker exception: " + e.Error.ToString()); 
     else 
      // Console.WriteLine("Complete: " + e.Result); 
    } 

答えて

2

_bw.ReportProgress(e.FileProcessedCount, e);は、OnFileProcessCompletedには入りません。このイベントは、DoWorkが完了すると発生します。進行状況バーを更新するには、それをDoWorkに配置する必要があります。私はこのようなFileProcessorにBackgroundWorkerのに渡す

private void DoWork (object sender, DoWorkEventArgs e) 
{  
    BackgroundWorker bg = sender as BackgroundWorker; 

    var files = GetFiles(); 
    int fileCount = files.Count; 

    var fileProcessor = new FileProcesser(); 
    for(int i = 0; i < fileCount; i++) 
    { 
     fileProcessor.ProcessFile(files[i]); 
     bg.ReportProgress((uint)((i/(double)fileCount) * 100)); 
    } 
} 

:それは次のようになりますのでFileProcesserで

private void DoWork (object sender, DoWorkEventArgs e) 
{ 
    BackgroundWorker bg = sender as BackgroundWorker;  
    var files = GetFiles(); 
    int fileCount = files.Count; 
    var fileProcessor=new FileProcesser(bg); 
    fileProcessor.ProcessFiles(files);   
} 

を、それは次のようになります。

private BackgroundWorker _bg; 
public FileProcessor(BackgroundWorker bg) 
{ 
    _bg = bg; 
} 

public void ProcessFiles(Files files) 
{ 
    // Process files 
    // ... 
    // Report Progress 
    _bg.ReportProgress(e.FileProcessedCount, e); 
} 
+0

実際には、 'RunWorkerCompleted'は' DoWork'が完了したときに起動されます。 'OnFileProcessCompleted'は' fileProcessor'によって生成されたイベントです。 – Aphex

+0

@Aphex - あなたは正しいと思われます。その場合、OPはBackgroundWorkerをFileProcessorに渡し、そこからReportProgressを呼び出す必要があります。完了したイベントを呼び出す必要はありません。 – SwDevMan81

0

を達成することができる方法の提案、一つの解決策は、BackgroundWorkerから派生したクラスを作り、それがイベントをサブスクライブします、そして、それは進歩を送信することです私のコードですイベントをイベントハンドラのUIスレッドに渡します。

関連する問題