run< R> статический метод
- @Since("2.19")
Выполняет 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