使用BackgroundWorker时如何向ProgressBar报告?

时间:2014-06-20 10:40:27

标签: c# .net winforms

我在form1中有一个progressBar1和BackgroundWorker,我点击按钮创建avi文件,我希望它根据avi文件创建进度向progressBar报告。

这是我创建avi文件的类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AviFile;
using System.Drawing;
using System.IO;

namespace WindowsFormsApplication1
{
    class CreateAvi
    {
        public static void AviMovie(FileInfo[] FileNames)
        {
            Bitmap bitmap = (Bitmap)Image.FromFile(FileNames[0].FullName);
            AviManager aviManager =
                new AviManager(@"c:\temp\new.avi", false);
            VideoStream aviStream =
                aviManager.AddVideoStream(false, 25, bitmap);
            int count = 0;
            for (int n = 1; n < FileNames.Length; n++)
            {
                if (FileNames[n].Length > 0)
                {
                    bitmap =
                       (Bitmap)Bitmap.FromFile(FileNames[n].FullName);
                    aviStream.AddFrame(bitmap);
                    bitmap.Dispose();
                    count++;
                }
            }
            aviManager.Close();
        }
    }
}

在form1中:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            CreateAvi.AviMovie(allfiles);
        }

进度:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {

        }

完成:

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

        }

这就是我在form1中所做的:

这是CreateAvi类中的方法我更改了它,因此它也将从form1获得后台工作者(称为变量bgw1):

public static void AviMovie(FileInfo[] FileNames,BackgroundWorker bgw1)
        {
            Bitmap bitmap = (Bitmap)Image.FromFile(FileNames[0].FullName);
            AviManager aviManager =
                new AviManager(@"c:\temp\new.avi", false);
            VideoStream aviStream =
                aviManager.AddVideoStream(false, 25, bitmap);
            int count = 0;
            for (int n = 0; n < FileNames.Length; n++)
            {
                if (FileNames[n].Length > 0)
                {
                    bitmap =
                       (Bitmap)Bitmap.FromFile(FileNames[n].FullName);
                    aviStream.AddFrame(bitmap);
                    bitmap.Dispose();
                    count++;
                    int pctDone = count * 100 / FileNames.Length;
                    bgw1.ReportProgress(pctDone);
                }
            }
            aviManager.Close();
        }

然后在form1中我更改了dowork事件,因此它将获得backgroundworker1:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            CreateAvi.AviMovie(allfiles,backgroundWorker1);
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            label9.Text = getallfiles[e.ProgressPercentage].FullName;
        }

所以progressBar真的达到100%到最后。但是,在label19中,我只看到文件000101.jpg,在这个idrectory中有167个文件,最后一个是000167.jpg

getallfiles是FileInfo[] 在form1构造函数中我做了:

var directory = new DirectoryInfo(mainDirectory);
getallfiles = directory.GetFiles("*.jpg");

我看到getallfiles包含167个文件。如何向标签报告正在处理的文件名?

3 个答案:

答案 0 :(得分:2)

使用ReportProgress

private void DoWork()
{
    // Calculate percent done
    backgroundWorker.ReportProgress(percentageComplete);
}

这将触发您可以安全更新UI的backgroundWorker1_ProgressChanged事件。

答案 1 :(得分:1)

需要从实际发生进展的方法调用

ReportProgress

public static void AviMovie(FileInfo[] FileNames,BackgroundWorker bgw1)
{
   Bitmap bitmap = (Bitmap)Image.FromFile(FileNames[0].FullName);
   AviManager aviManager =new AviManager(@"c:\temp\new.avi", false);
   VideoStream aviStream =aviManager.AddVideoStream(false, 25, bitmap);
   int count = 0;
   for (int n = 0; n < FileNames.Length; n++)
   {
      if (FileNames[n].Length > 0)
      {
         bitmap =(Bitmap)Bitmap.FromFile(FileNames[n].FullName);
         aviStream.AddFrame(bitmap);
         bitmap.Dispose();
         count++;
         int pctDone = count * 100 / FileNames.Length;
         bgw1.ReportProgress(pctDone);
       }
    }
    aviManager.Close();
}

此外,你的循环需要从0开始 - 你正在跳过FileNames中的第一个元素。

编辑:在后台工作人员的ProgressChanged事件中,您无法使用e.ProgressPercentage作为数据索引,您必须从获得索引的百分比:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {
   progressBar1.Value = e.ProgressPercentage;
   int fileIndex = e.ProgressPercentage * FileNames.Length/100;
   label9.Text = getallfiles[fileIndex].FullName; 
}

答案 2 :(得分:0)

你应该将AviMovie()的主体放入bgw_DoWork(),并将这些行添加到正文的顶部:

FileInfo fileInfo = (FileInfo[])e.Argument;
int steps = fileInfo.Length;
BackgroundWorker bgw = (BackgroundWorker)sender;

在for循环的末尾添加此行:

bgw.ReportProgress((int)(100 / steps) * n, null);

用这个启动工人:

bgw.RunWorkerAsync(FileNames); //FileNames is of course the array

当然还有其他方法可以做到,但这可能就是我要做的。