protected void AcknowledgeCancel()
{
lock (this)
{
cancelAcknowledgedFlag = true;
isRunning = false;
// Pulse the event in case the main thread is blocked
// waiting for us to finish (e.g. in CancelAndWait or
// WaitUntilDone).
Monitor.Pulse(this);
// Using async invocation to avoid a potential deadlock
// - using Invoke would involve a cross-thread call
// whilst we still held the object lock. If the event
// handler on the UI thread tries to access this object
// it will block because we have the lock, but using
// async invocation here means that once we've fired
// the event, we'll run on and release the object lock,
// unblocking the UI thread.
FireAsync(Cancelled, this, EventArgs.Empty);
}
}