I'm having trouble working out how I can catch exceptions from isolates. With the following code, I've tried everything I can think of to handle the error that is thrown from task, but it's still marked as Unhandled exception.
void main() async {
try {
var rp = ReceivePort();
rp.listen((message) {
print(message);
}, one rror: (e) {
print(e);
});
rp.handleError((e) {
print(e);
});
var isolate = await Isolate.spawn(task, rp.sendPort);
isolate.addErrorListener(rp.sendPort);
} catch (e) {
print(e);
}
}
void task(SendPort sp) {
sp.send('hello from isolate');
throw Exception();
}
What am I missing here?
EDIT: From the below answer, my solution should look like this:
void main() async {
var rp = ReceivePort();
var errorRp = ReceivePort();
errorRp.listen((e) {
print('exception occured');
print(e);
});
rp.listen(print);
await Isolate.spawn(task, rp.sendPort, one rror: errorRp.sendPort);
await Future.delayed(Duration(seconds: 1));
rp.close();
errorRp.close();
}
void task(SendPort sp) {
sp.send('hello from isolate');
throw Exception();
}
CodePudding user response:
I think you have missed an important segment of the documentation for Isolate.spawn:
You can also call the
setErrorsFatal,addOnExitListenerandaddErrorListenermethods on the returned isolate, but unless the isolate was started aspaused, it may already have terminated before those methods can complete.
You issue is that your spawned Isolate has already executed throw Exception() before your isolate.addErrorListener(rp.sendPort); has been executed.
Instead, do something like this to spawn the Isolate as paused and then later resume it:
var isolate = await Isolate.spawn(task, rp.sendPort, paused: true);
isolate.addErrorListener(rp.sendPort);
isolate.resume(isolate.pauseCapability!);
Alternative, you can just give the Isolate your error handler as part of spawning:
var isolate = await Isolate.spawn(task, rp.sendPort, one rror: rp.sendPort);
