Вы используете экземпляр
BackgroundWorker, который живет на уровне класса.
Всякий раз, когда вы нажимаете на кнопку, к экземпляру
BackgroundWorker подключается новый обработчик события
DoWork. Т.е. нажмете один раз на кнопку, будет один обработчик, нажмете два раза, то уже будет два обработчика, нажмете десять раз - будет десять обработчиков и все они будут работать. Это будет хорошо видно, когда обработчиков будет много, из-за рассинхронизации значение
i будет меняться быстрее, хаотичней. Так что вывод переменной на уровень класса и присваивание ей нулевого значения - это не решение проблемы.
В данном случае, можно либо всякий раз при нажатии на кнопку создавать новый экземпляр
BackgroundWorker:
private void button2_Click(object sender, EventArgs e) // запуск таймера класс BackgroundWorker
{
// создаем новый экземпляр BackgroundWorker
bw = new BackgroundWorker();
// остальной код
key = true;
// ...
}
Либо отключать обработчик, но для этого придется иметь ссылку на него (
bw.DoWork -= ссылкаНаОбработчик). При таком варианте проще отказаться от анонимных функций и использовать обычные.
Если интересно, то количество обработчиков события
DoWork у экземпляра
BackgroundWorker можно проверить так:
EventHandlerList events = (EventHandlerList)typeof(Component).GetProperty
(
"Events",
BindingFlags.NonPublic | BindingFlags.Instance
).GetValue(bw, null);
var k = typeof(BackgroundWorker).GetField
(
"doWorkKey",
BindingFlags.NonPublic | BindingFlags.Static
).GetValue(null);
var handlers = events[k];
Console.WriteLine
(
"Обработчиков {0}",
handlers.GetInvocationList().Length
);