Spec-Zone.ru › Dart 2

dart:isolate

run<R> статический метод

  1. @Since("2.19")
Future<R> run<R>(
  1. FutureOr<R> computation( ),
  2. {String? debugName}
)

Выполняет computation в новом изоляте и возвращает результат.

int slowFib(int n) =>
    n <= 1 ? 1 : slowFib(n - 1) + slowFib(n - 2);

// Compute without blocking current isolate.
var fib40 = await Isolate.run(() => slowFib(40));

Если computation является асинхронным (возвращает Future<R>), то этот Future ожидается в новом изоляте, где завершается всё асинхронное вычисление, прежде чем будет возвращён результат.

int slowFib(int n) =>
    n <= 1 ? 1 : slowFib(n - 1) + slowFib(n - 2);
Stream<int> fibStream() async* {
  for (var i = 0;; i++) yield slowFib(i);
}

// Returns `Future<int>`.
var fib40 = await Isolate.run(() => fibStream().elementAt(40));

Если computation выбрасывает исключение, изолят завершается, а эта функция выбрасывает то же исключение.

Future<int> eventualError() async {
  await Future.delayed(const Duration(seconds: 1));
  throw StateError("In a bad state!");
}

try {
  await Isolate.run(eventualError);
} on StateError catch (e, s) {
  print(e.message); // In a bad state!
  print(LineSplitter.split("$s").first); // Contains "eventualError"
}

Любые необработанные асинхронные ошибки также приведут к завершению вычисления, но будут представлены как RemoteError, поскольку addErrorListener не предоставляет исходный объект ошибки.

Результат отправляется с помощью exit, а значит, передаётся этому изоляту без копирования.

Функция computation и её результат (или ошибка) должны быть передаваемыми между изолятами.

Значение debugName используется только для присвоения имени новому изоляту при отладке.

Реализация

@Since("2.19")
static Future<R> run<R>(FutureOr<R> computation(), {String? debugName}) {
  var result = Completer<R>();
  var resultPort = RawReceivePort();
  resultPort.handler = (response) {
    resultPort.close();
    if (response == null) {
      // onExit handler message, isolate terminated without sending result.
      result.completeError(
          RemoteError("Computation ended without result", ""),
          StackTrace.empty);
      return;
    }
    var list = response as List<Object?>;
    if (list.length == 2) {
      var remoteError = list[0];
      var remoteStack = list[1];
      if (remoteStack is StackTrace) {
        // Typed error.
        result.completeError(remoteError!, remoteStack);
      } else {
        // onError handler message, uncaught async error.
        // Both values are strings, so calling `toString` is efficient.
        var error =
            RemoteError(remoteError.toString(), remoteStack.toString());
        result.completeError(error, error.stackTrace);
      }
    } else {
      assert(list.length == 1);
      result.complete(list[0] as R);
    }
  };
  try {
    Isolate.spawn(_RemoteRunner._remoteExecute,
            _RemoteRunner<R>(computation, resultPort.sendPort),
            onError: resultPort.sendPort,
            onExit: resultPort.sendPort,
            errorsAreFatal: true,
            debugName: debugName)
        .then<void>((_) {}, onError: (error, stack) {
      // Sending the computation failed asynchronously.
      // Do not expect a response, report the error asynchronously.
      resultPort.close();
      result.completeError(error, stack);
    });
  } on Object {
    // Sending the computation failed synchronously.
    // This is not expected to happen, but if it does,
    // the synchronous error is respected and rethrown synchronously.
    resultPort.close();
    rethrow;
  }
  return result.future;
}

© 2012 the Dart project authors
Licensed under the BSD 3-Clause "New" or "Revised" License.
https://api.dart.dev/stable/2.19.6/dart-isolate/Isolate/run.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API