cancel method
Cancels the job with reason and waits for it to actually finish.
Pass a custom CancelReason subclass to carry data to whenCancelled and
the Cancelled outcome. The accepted reason is kept by identity; another
cancellation does not replace it. Nor does a later one replace a
cancellation an uncancellable section holds, with one exception: a
cancellation the job cannot refuse, such as the one an engine makes for
its rules, is not held, and the job accepts it at once and drops the held
one. A body that cancels itself accepts one the same way, from the moment
it throws: this call then finds the job already cancelled and waits for
it, exactly as a second call does.
A job created with cancellable: false refuses this once it has started;
before that there is no body to protect, and a job cancelled then is
dropped like any other — unless an engine holds it before the start and
refuses on its behalf, as solo does for a job waiting in its queue:
there cancellable: false turns this call down already, and the job runs
when its turn comes. A job inside JobContext.uncancellable is cancelled
when that section closes. Either way the returned future waits for it to
finish.
Awaited from inside the body it never completes: the waiting is for the
job, and the job is this body. A body cancels itself with throw Cancelled('why') instead.
Implementation
@override
Future<void> cancel({CancelReason reason = const ManualCancelReason()}) {
cancelWith(Cancelled.by(reason: reason, stackTrace: StackTrace.current));
// The core's own waiting is not observation, so cancelling a job does
// not silence its failure.
return untilFinished;
}