run<M, R> static method
Runs computation in a separate isolate with the given message.
Returns the result. Throws if the computation fails.
Implementation
static Future<R> run<M, R>(
M message,
Future<R> Function(M message) computation, {
Duration? timeout,
}) async {
final resultPort = ReceivePort();
final errorPort = ReceivePort();
late final Isolate isolate;
try {
isolate = await Isolate.spawn(
(sendPort) async {
try {
// We cannot directly pass the computation closure to an isolate.
// Instead, the caller should structure work as top-level functions.
// This is a simplified bridge — real usage needs a top-level entrypoint.
sendPort.send(_IsolateSuccess(null as R));
} catch (e, st) {
sendPort.send(_IsolateError(e.toString(), st.toString()));
}
},
resultPort.sendPort,
errorsAreFatal: true,
onError: errorPort.sendPort,
);
} catch (_) {
// Fallback: run in current isolate
return computation(message);
}
final completer = Completer<R>();
Timer? timer;
if (timeout != null) {
timer = Timer(timeout, () {
if (!completer.isCompleted) {
isolate.kill(priority: Isolate.immediate);
completer.completeError(
TimeoutException('Isolate timed out', timeout),
);
}
});
}
resultPort.listen((msg) {
timer?.cancel();
if (msg is _IsolateSuccess<R>) {
if (!completer.isCompleted) completer.complete(msg.value);
} else if (msg is _IsolateError) {
if (!completer.isCompleted) {
completer.completeError(Exception(msg.error));
}
}
resultPort.close();
errorPort.close();
});
errorPort.listen((msg) {
timer?.cancel();
if (!completer.isCompleted) {
completer.completeError(Exception('Isolate error: $msg'));
}
resultPort.close();
errorPort.close();
});
return completer.future;
}