Вы можете использовать BackgroundWorker и по-прежнему перемещать свой рабочий код за пределы класса Form. У вашего класса Worker есть метод Work. Пусть Work принимает BackgroundWorker в качестве параметра и перегружает метод Work сигнатурой, отличной от BackgroundWorker, которая отправляет нулевое значение первому методу.
Затем в своей форме используйте BackgroundWorker с ProgressReporting, а в своей Работе (BackgroundWorker bgWorker, params object [] otherParams) вы можете включать такие выражения, как:
if( bgWorker != null && bgWorker.WorkerReportsProgress )
{
bgWorker.ReportProgress( percentage );
}
... и аналогичным образом включают проверки для CancellationPending.
Тогда в вашем коде форм вы можете обрабатывать события. Сначала установите bgWorker.DoWork += new DoWorkEventHandler( startBgWorker );
, где этот метод запускает ваш метод Worker.Work, передавая bgWorker в качестве аргумента.
Это можно затем запустить из события кнопки, которое называется bgWorker.RunWorkerAsync.
Затем вторая кнопка отмены может вызвать bgWorker.CancelAsync, которая затем попадет в ваш раздел, где вы проверили отмену отмены.
В случае успеха или отмены вы будете обрабатывать событие RunWorkerCompleted, где вы проверяете, был ли работник отменен. Тогда, если это не так, вы предполагаете, что все прошло успешно, и идете по этому пути.
Перегрузив метод Work, вы можете сохранить его для повторного использования из кода, который не заботится о Forms или ComponentModel.
И, конечно же, вы реализуете событие progressaged без необходимости заново изобретать колесо на этом. ProTip: ProgressChangedEventArgs принимает значение типа int, но не заставляет его превышать 100. Чтобы сообщить более мелкий процент прогресса, передайте аргумент с множителем (скажем, 100), так что 14,32% будет прогрессом 1432. Затем вы можете отформатируйте отображение, либо переопределите индикатор выполнения, либо отобразите его в виде текстового поля. (все с DRY-дружественным дизайном)