BackgroundWorker progressBar - 在另一个类中发生循环时实现ReportProgress的问题

时间:2011-01-21 19:52:06

标签: c#

您好 我正在尝试将后台工作程序与进度条集成,但无法使其正确。

我正在处理一些文件,所有处理都在外部类中完成。

我的困难在于循环是在这个课程中,通常我会和背景工作者交谈。

好处是,在处理文件时,只要每个文件都已完成处理,就会触发事件。

这是我的代码,任何建议如何实现

    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 个答案:

答案 0 :(得分:2)

_bw.ReportProgress(e.FileProcessedCount, e);不应该进入OnFileProcessCompletedDoWork完成时会触发此事件。您应该将其放在DoWork中以更新进度条。所以它看起来像这样:

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));
   } 
}

我会将BackgroundWorker传递给FileProcessor,如下所示:

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);          
}

在FileProcesser中,它看起来像这样:

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

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

答案 1 :(得分:0)

在这种情况下,一种解决方案是从BackgroundWorker创建派生类,使其订阅事件,并将progress事件发送到事件处理程序中的UI线程。