BackgroundWorker создает проблему в С# при добавлении элемента в список?

У меня есть список, в котором я должен указать минимум 2 файла для слияния. слияние выполняется, когда я нажимаю кнопку «Объединить». Запускается индикатор выполнения и появляется окно сообщения о том, что файлы были объединены. Я использую фоновый рабочий для запуска индикатора выполнения.

Теперь проблема заключается в том, что когда слияние выполняется с 2 файлами, я добавляю еще один файл, нажмите кнопку слияния, появляется сообщение о слиянии. Я нажимаю «ОК» в окне сообщения, снова появляется окно сообщения с тем же сообщением, что слияние было выполнено. Это окно сообщения продолжает появляться столько раз, сколько раз я добавляю файл в список.

Например, для 2 файлов появляется сообщение 1ce den при добавлении еще 1 файла появляется сообщение 2ice , еще 1 файл в списке появляется сообщение 3ic. Как и в случае с dis, оно продолжается....

Когда я использовал отладчик для его отслеживания, я заметил, что мое событие Background Worker Runcompleted вызывается столько раз, когда я добавляю файл в список. Вот код для события Click кнопки Merge...

Worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
Worker.RunWorkerCompleted +=
    new  RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted);
Worker.WorkerSupportsCancellation = true;

if (!Worker.IsBusy)
    Worker.RunWorkerAsync();
else
    MessageBox.Show("Cannot run background worker twice ");

if (Worker.IsBusy)
{
    progress = new ProgressDialogDTB();
    progress.FormClosing += 
        new FormClosingEventHandler(ProgressDialog_FormClosing);
    progress.ShowDialog(this);
}
while (Worker.IsBusy)
{
    Application.DoEvents();
}

//For Background Worker completed Event...
private void Worker_RunWorkerCompleted(object sender, 
    AsyncCompletedEventArgs e)
{            
    if (progress != null)
    {
        progress.Close();
        progress = null;
    }
    if ( e.Cancelled )
        MessageBox.Show(" Progress was cancelled ");                               

    if (e.Error == null)
        if (!e.Cancelled)
            MessageBox.Show("Files has been merged ");

    if (e.Error != null)
        MessageBox.Show(e.Error.Message);     
}//Worker_RunWorkerCompleted

Я не знаю, где я ошибаюсь. Пожалуйста, помогите... Спасибо...


person crazy_itgal    schedule 23.06.2009    source источник
comment
Можете поделиться рабочим кодом? Что представляет собой завершение? Если он вызывается x раз, то само собой разумеется, что ваш рабочий процесс указывает, что он завершен x раз, либо потому, что он так работает, либо он создается x раз.   -  person Lazarus    schedule 23.06.2009
comment
Много кода, но ни один из них не имеет отношения к проблеме.   -  person    schedule 23.06.2009
comment
Без понятия о вашей проблеме. Но я бы еще раз подумал: while (Worker.IsBusy){ Application.DoEvents();} тоже. Жрет процессорное время! (или это было только для тестирования?)   -  person Dr Spack    schedule 23.06.2009


Ответы (2)


Я предполагаю, что при каждом нажатии кнопки Merge вы регистрируете нового делегата. Если следующий код:

Worker.DoWork += new System.ComponentModel.DoWorkEventHandler(Worker_DoWork);
Worker.RunWorkerCompleted += new  System.ComponentModel.RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted);

находится в обработчике события нажатия кнопки «Объединить», рассмотрите возможность его переноса в метод инициализации формы. Вам нужно зарегистрировать делегата только один раз. В следующий раз, когда вы это сделаете, он добавит новый, поэтому при втором щелчке слияния он будет выполняться дважды, при третьем щелчке - три раза и так далее.

person Robert Wilczynski    schedule 23.06.2009
comment
Спасибо ... это сработало .... еще одна вещь, мой индикатор выполнения все еще работает, когда появляется окно сообщения о том, что файлы были объединены. Как скрыть индикатор выполнения перед появлением окна сообщения? - person crazy_itgal; 23.06.2009
comment
У тебя получилось? Я предполагаю, что проблема заключалась в том, что в рабочем обработчике завершенных событий код под условием if (progress! = null), отвечающий за закрытие диалогового окна, не выполняется (условие оценивается как ложное)? - person Robert Wilczynski; 23.06.2009

Если ваш рабочий процесс является переменной уровня модуля, и вы добавляете его в список вызовов каждый раз, когда нажимается кнопка, этот метод будет вызываться каждый раз. Скажем, вы нажали 3 раза, тогда этот код Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted); будет выполнен 3 раза и будет вызван 3 раза. Установите обработчик Completed один раз при создании экземпляра рабочего объекта.

Ба! Избили до этого!

person Simon Wilson    schedule 23.06.2009