2013-05-08 2 views
0

У меня есть метод загрузки файлов. Иногда это занимает много времени, поэтому я хотел бы показать пользователю окно progressBar, с помощью которого он может минимизировать все приложение или отменить ход.Как использовать BackgroundWorker с настраиваемым диалогом прогресса (Form with ProgressBar)?

Я читал кучу учебников о BackgroundWorkers и ProgressBars, но ни один из них не охватывает сценарий, когда ProgressBar находится в какой-то другой форме. Я не знаю, когда именно я должен открыть новую форму и как получить доступ к индикатору выполнения.

До сих пор я пытался:

MainForm:

private void addFolderToolStripMenuItem_Click(object sender, EventArgs e) 
{ 
    ctlFolderSelectDialog dlg = new ctlFolderSelectDialog(); 
    if (dlg.ShowDialog() == DialogResult.OK) 
    { 
     BackgroundWorker.RunWorkerAsync(dlg); // to pass some variables from ctlFolderSelectDialog 
    } 
} 

private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    Form_Dialogs.ProgressDialog progressDialog = new Form_Dialogs.ProgressDialog(); 
    progressDialog.ShowDialog(); // open the progress dialog window 

    myClass.loadFiles((ctlFolderSelectDialog)e.Argument); // THE WORK 

    progressDialog.Close(); // close the progress window - in here? 
} 

MyClass:

public void loadFiles(ctlFolderSelectDialog dlg) 
{ 
    ... 
    files.Count() // somehow report this preliminary number of files to ProgressBar window - to set ProgressBar1.Maximum value 
    ... 
    foreach (file in files) 
    { 
     loadFile(); 
     ... // here I should somehow udpate the progressBar on the other window - performStep() 
    } 
} 

ProgressDialog:

private void ProgressDialog_Load(object sender, EventArgs e) 
{ 
    progressBar1.Value = 0; 
    progressBar1.Maximum = 100; // how to get this value from myClass function? Pass in ProgressDialog contructor? 
    progressBar1.Step = 1; 
} 

public void UpdateProgress(int progress) 
{ 
    progressBar1.PerformStep(); 
} 

ответ

1

BackgroundWorker поддерживает прогресс обновления через событие ProgressChanged.

Внутри метода loadFiles() вам необходимо рассчитать прогресс в% и внутри цикла foreach. backgroundWorker.ReportProgress(percentage). Это приведет к событию ProgressChanged, из которого вы можете получить в аргументе события e.ProgressPercentage. [Вам понадобится ссылка на BackgroundWorker внутри метода ]

В форме ProgressDialog вам необходимо зарегистрироваться, чтобы войти в это событие. Вы можете передать BackgroundWorker в конструкторе, например.

public void ProgressDialog(BackgroundWorker worker) 
{ 
    worker.ProgressChanged += ProgressDialog_ProgressChanged; 
} 

private void ProgressDialog_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    UpdateProgressBar(e.ProgressPercentage); 
} 

и в основной форме:

private void addFolderToolStripMenuItem_Click(object sender, EventArgs e) 
{ 
    ctlFolderSelectDialog dlg = new ctlFolderSelectDialog(); 
    if (dlg.ShowDialog() == DialogResult.OK) 
    { 
     BackgroundWorker.RunWorkerAsync(dlg); // to pass some variables fromctlFolderSelectDialog 
     Form_Dialogs.ProgressDialog progressDialog = 
      new Form_Dialogs.ProgressDialog(BackgroundWorker); // Pass the BackgroundWorker instance 
     progressDialog.ShowDialog(); // open the progress dialog window 
     // No need to explicitly close it. A dialog form is destroyed when closed by the user. 
    } 
} 

private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    myClass.loadFiles((ctlFolderSelectDialog)e.Argument); // THE WORK 
} 
+0

Спасибо, единственная проблема теперь в том, что он не будет называть: dataGridView_DataBindingComplete(), как я могу это сделать? Btw myClass.loadFiles() сначала загружает файлы в список <>, а затем помещает список в DataSet, привязанный к DataGridView. Если я хочу, чтобы прогресс прошел снова с нуля, чтобы измерить процесс загрузки списка <> в DataSet, должен ли я создать еще один BackgroundWorker и запустить его в первом методе BackgroundWorker_RunWorkerCompleted()? Или я должен делать оба процесса в одном потоке BackgroundWorker? –

+0

1. Просьба предоставить более подробную информацию о вызове dataGridView_DataBindingComplete(). 2. Почему вы хотите показать индикатор выполнения для загрузки файлов в набор данных? Требуется ли более 1 секунды? Я ожидал бы несколько миллисекунд. – Michael

+0

Я использую библиотеку TagLib для чтения музыкальных тегов ID3. При вызове myClass.loadFiles() он проходит через данную структуру каталогов и заполняет список . В этом есть индикатор выполнения. Затем вызывается метод fillDataset, который берет список, и для каждой песни-элемента (может быть 10 000) он считывает информацию ID3, такую ​​как имя песни, исполнитель, длина и .. и добавляет строку в набор данных. Это обычно занимает то же время, что и прохождение через структуру каталогов (~ 10 секунд). –

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