Я решил добавить к этому еще один ответ, так как поток комментариев к предыдущему посту становится довольно длинным, и редактирование моего текущего ответа слишком сильно его расширит.
Я немного озадачен вашим кодом - я не знаю, изменили ли вы его с момента публикации или нет. У меня есть несколько замечаний по этому вопросу:
Убедитесь, что при подключении / отключении обработчиков событий к / от событий, которые вы не вызываете new
для делегата. Просто используйте название метода (как указано в ответе выше - см. Ниже).
Если вы не используете registerHandlers(...)
и unregisterHandlers(...)
в других местах, то я не вижу необходимости передавать делегаты, особенно если методы находятся в одном классе с этими делегатами. Конечно, метод может позволять знать этих делегатов и добавлять / удалять их соответственно.
Вы изначально заявили, что ваш метод backgroundWorker1_RunWorkerCompleted
выполнялся более одного раза, даже после отсоединения от события. Из того, что я вижу в вашем отредактированном коде, это вполне правдоподобно, поскольку вы нигде не снимаете этот обработчик событий. Вместо этого вы открепляете обработчик workerCompleted
. Кроме того, тот факт, что вы назвали локальную переменную (внутри unregisterHandlers(...)
) для делегата RunWorkerCompleted
так же, как и фактический метод, может вызвать путаницу для компилятора (я не уверен в этом, но это может показаться вероятным мне).
Итак, в свете этих моментов я бы изменил приведенный выше код на что-то более похожее на это:
private BackgroundWorker mBackgroundWorker; // Instantiated elsewhere
#region Registration
private void RegisterHandlers()
{
// Hook up to the background worker events
mBackgroundWorker.RunWorkerCompleted += mBackgroundWorker_RunWorkerCompleted;
mBackgroundWorker.DoWork += mBackgroundWorker_DoWork;
mBackgroundWorker.ProgressChanged += mBackgroundWorker_ProgressChanged;
}
private void UnregisterHandlers()
{
// Unhook from the background worker events
mBackgroundWorker.RunWorkerCompleted -= mBackgroundWorker_RunWorkerCompleted;
mBackgroundWorker.DoWork -= mBackgroundWorker_DoWork;
mBackgroundWorker.ProgressChanged -= mBackgroundWorker_ProgressChanged;
}
#endregion
#region Event Handlers
private void Button1_Click(object sender, EventArgs e)
{
RegisterHandlers();
// Start the background worker
mBackgroundWorker.RunWorkerAsync();
}
private void mBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
try
{
// ...
}
finally
{
UnregisterHandlers();
}
}
private void mBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
// ...
}
private void mBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// ...
}
#endregion
Обратите внимание, что имена методов и переменных не совсем совпадают с вашими собственными, поэтому вам нужно быть осторожным, чтобы изменить их соответствующим образом. Однако, если вы внимательно посмотрите на то, как написан код, вы должны понять, что я имею в виду в отношении перехвата / открепления обработчиков событий.
Надеюсь, это поможет.
EDIT
Я написал небольшое тестовое приложение, чтобы вручную проверить вашу проблему, и, следуя изложенным мною пунктам, у меня нет проблем. Исходный код моего тестового приложения можно найти на PasteBin . Результаты, напечатанные в моем окне вывода в Visual Studio:
Worker 1: Do Work
Worker 1: Run Worker Completed
Worker 2: Do Work
Worker 2: Run Worker Completed
Worker 1: Do Work
Worker 1: Run Worker Completed
Worker 2: Do Work
Worker 2: Run Worker Completed
Приведенный выше вывод является результатом нажатия рабочих кнопок в последовательности: работник 1, работник 2, работник 1, работник 2.
РЕДАКТИРОВАТЬ 2
В ответ на вашу попытку управления обработчиками событий сгенерированного дизайнером BackgroundWorker
; Я полагаю, что в вашем коде происходит следующее:
- Код, сгенерированный дизайнером WinForms, создает экземпляр
backgroundWorker1
.
- Код, сгенерированный дизайнером WinForms, перехватывает обработчики событий
backgroundWorker1
(количество обработчиков: 1).
- Пользователь нажимает
button1
.
- Ваш код перехватывает обработчики событий на
backgroundWorker1
(количество обработчиков: 2). Это то место, где вы собираетесь получить несколько зацепок.
Если это является тем, что происходит, то вы должны быть в состоянии запретить сгенерированному дизайнером коду перехватывать события, удаляя любые обработчики событий, указанные в части «События» таблицы свойств конструктора форм.