Я сделал что-то похожее на это. Есть веская причина, если у вас есть несколько задач, которые вы хотите выполнить, но вы не хотите, чтобы код BackgroundWorker реплицировался по всему проекту. У меня нет индикатора выполнения, привязанного к реальному базовому классу, у меня это просто в основной форме. Вот решение, которое я придумал:
Ниже приведен базовый класс:
public abstract class Operation
{
#region public Event Handlers
///
/// The event that updates the progress of the operation
///
public event OperationProgressChangedEventHandler OperationProgressChanged;
///
/// The event that notifies that the operation is complete (and results)
///
public event OperationCompletedEventHandler OperationCompleted;
#endregion
#region Members
// Whether or not we can cancel the operation
private bool mWorkerSupportsCancellation = false;
// The task worker that handles running the operation
private BackgroundWorker mOperationWorker;
// The operation parameters
private object[] mOperationParameters;
#endregion
///
/// Base class for all operations
///
public Operation(params object[] workerParameters)
{
mOperationParameters = workerParameters;
// Setup the worker
SetupOperationWorker();
}
#region Setup Functions
///
/// Setup the background worker to run our Operations
///
private void SetupOperationWorker()
{
mOperationWorker = new BackgroundWorker();
mOperationWorker.WorkerSupportsCancellation = mWorkerSupportsCancellation;
mOperationWorker.WorkerReportsProgress = true;
mOperationWorker.WorkerSupportsCancellation = true;
mOperationWorker.DoWork += new DoWorkEventHandler(OperationWorkerDoWork);
mOperationWorker.ProgressChanged += new ProgressChangedEventHandler(OperationWorkerProgressChanged);
mOperationWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OperationWorkerRunWorkerCompleted);
}
#endregion
#region Properties
///
/// Whether or not to allow the user to cancel the operation
///
public bool CanCancel
{
set
{
mWorkerSupportsCancellation = value;
}
}
#endregion
#region Operation Start/Stop Details
///
/// Start the operation with the given parameters
///
/// The parameters for the worker
public void StartOperation()
{
// Run the worker
mOperationWorker.RunWorkerAsync(mOperationParameters);
}
///
/// Stop the operation
///
public void StopOperation()
{
// Signal the cancel first, then call cancel to stop the test
if (IsRunning())
{
// Sets the backgroundworker CancelPending to true, so we can break
// in the sub classes operation
mOperationWorker.CancelAsync();
// This allows us to trigger an event or "Set" if WaitOne'ing
Cancel();
// Wait for it to actually stop before returning
while (IsRunning())
{
Application.DoEvents();
}
}
}
///
/// Whether or not the operation is currently running
///
///
public bool IsRunning()
{
return mOperationWorker.IsBusy;
}
#endregion
#region BackgroundWorker Events
///
/// Fires when the operation has completed
///
///
///
private void OperationWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Allow the sub class to clean up anything that might need to be updated
Clean();
// Notify whoever is register that the operation is complete
if (OperationCompleted != null)
{
OperationCompleted(e);
}
}
///
/// Fires when the progress needs to be updated for a given test (we might not care)
///
///
///
private void OperationWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Notify whoever is register of what the current percentage is
if (OperationProgressChanged != null)
{
OperationProgressChanged(e);
}
}
///
/// Fires when we start the operation (this does the work)
///
///
///
private void OperationWorkerDoWork(object sender, DoWorkEventArgs e)
{
// Run the operation
Run(sender, e);
}
#endregion
#region Abstract methods
///
/// Abstract, implemented in the sub class to do the work
///
///
///
protected abstract void Run(object sender, DoWorkEventArgs e);
///
/// Called at the end of the test to clean up anything (ex: Disconnected events, etc)
///
protected abstract void Clean();
///
/// If we are waiting on something in the operation, this will allow us to
/// stop waiting (ex: WaitOne).
///
protected abstract void Cancel();
#endregion
}