run method

  1. @override
Future<T> run()
override

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;
}