run method
Executes the computation and returns the computation result (or throws the exception), or throws the CancellationException exception.
Implementation
@override
Future<T> run() async {
if (_isStarted) {
throw StateError('The computation can be run only once');
}
_isStarted = true;
if (_isTerminationRequested) {
throw CancellationException();
}
if (_token != null) {
_token!.throwIfCanceled();
}
var hasResult = false;
T? result;
final completer = Completer<T>();
unawaited(Zone.root.run(() async {
unawaited(() async {
try {
result = await _zone.run(() {
return Task.run(token: _token, () async {
await Future<void>.delayed(Duration.zero);
return _computation();
});
});
hasResult = true;
} catch (e, s) {
if (_error == null) {
_error = e;
_stackTrace = s;
}
}
if (!_completer.isCompleted) {
_completer.complete();
}
}());
await _completer.future;
try {
if (_isTerminationRequested) {
completer.completeError(CancellationException(), StackTrace.current);
} else if (_error != null) {
completer.completeError(_error!, _stackTrace ?? StackTrace.empty);
} else if (hasResult) {
completer.complete(result as T);
} else {
completer.completeError(
StateError('Computation ended without result'),
StackTrace.current);
}
} finally {
final onExit = _onExit;
if (onExit != null) {
onExit(this);
}
}
}));
return completer.future;
}