2014-06-20 3 views
1

У меня есть в form1 progressBar1 и BackgroundWorker и я, когда нажимаю кнопку, чтобы создать avi-файл, я хочу, чтобы он сообщал progressBar в соответствии с прогрессом создания файла avi.Как мне сообщить ProgressBar при работе с BackgroundWorker?

Это класс, где я создаю файл 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 я изменил его так, он получит также BackgroundWorker от 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 файлов. Как я могу сообщить метке имена файлов, которые являются процессами?

+0

Вы можете создать метод в форме1, который обновляет значение вашего ProgressBar (потенциально selfinvoking). Затем eigther обратится к нему или реорганизует ваш CreateAviClass, чтобы он принял делегата этого метода, который вы могли бы вызвать из своего тогда нестатического метода AviMovie. * Редактировать: * или просто использовать метод ReportProgress для Фонового Работника, как предложено DGibbs – MrPaulch

+0

Посмотрите на мой квест, пожалуйста, обновите его тем, что я пытался сообщить именам файлов для labe – user3756594

+0

Отредактировал свой вопрос еще до того, как я не показал, что я изменил в createavi class i изменил метод, чтобы он получил backgroundworker1. – user3756594

ответ

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.

EDIT: В 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; 
} 
+0

Как назначить метке имя каждого файла, который в данный момент обрабатывается? Я попытался в форме1 в событии progressworker сделать make: label9.Text = allfiles [e.ProgressPercentage] .FullName; но когда уровень прогресса доходит до 100%, я вижу только файл 000101.jpg, а последний файл в каталоге - 000167.jpg – user3756594

+0

C-Pound посмотрите на мои поиски, пожалуйста, обновите его тем, что я пытался сообщить имена файлов на метка. – user3756594

+0

Я также видел, что FileNames в классе CreateAvi также содержат 167 файлов. Так почему я вижу только 101 файл в отчете о ходе работы? – user3756594

2

С помощью ReportProgress

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

Этот вызовет backgroundWorker1_ProgressChanged событие, которое вы имеете, где вы можете обновить пользовательский интерфейс безопасно.

+0

DGibbs посмотрел на мой вопрос, обновленный тем, что я сделал до сих пор, но он не работает. – user3756594

+0

Как вы это пробовали, вы сообщаете о своем прогрессе только после того, как вы закончили с «AviMovie» – MrPaulch

+1

Ну, для начала вы не вычисляете процентное значение ... Вам нужно сообщить о прогрессе изнутри «AviMovie». Вы сообщаете об этом после завершения операции. – DGibbs

0

Вы должны поставить тело AviMovie() в bgw_DoWork(), и добавьте эти строки в верхней части тела:

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

Добавьте эту строку в конце для цикла:

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

и начать работник с этим:

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

Есть другие способы сделать это, конечно, но это, вероятно, что я буду делать.

Смежные вопросы