Gazihan Alankus
Gazihan Alankus

Reputation: 11984

Invoking async function without await in Dart, like starting a thread

I have two functions

callee() async {
  // do something that takes some time
} 

caller () async {
  await callee();
}

In this scenario, caller() waits till callee() finishes. I don't want that. I want caller() to complete right after invoking callee(). callee() can complete whenever in the future, I don't care. I just want to start it just like a thread and then forget about it.

Is this possible?

Upvotes: 24

Views: 14941

Answers (2)

lrn
lrn

Reputation: 71623

When you call the callee function, it returns a Future. The await then waits for that future to complete. If you don't await the future, it will eventually complete anyway, but your caller function won't be blocked on waiting for that. So, you can just do:

caller() {
  callee();  // Ignore returned Future (at your own peril).
}

If you do that, you should be aware of what happens if callee fails with an error. That would make the returned future complete with that error, and if you don't listen on the future, that error is considered "uncaught". Uncaught errors are handled by the current Zone and the default behavior is to act like a top-level uncaught error which may kill your isolate.

So, remember to handle the error.

If callee can't fail, great, you're done (unless it fails anyway, then you'll have fun debugging that).

Actually, because of the risk of just forgetting to await a future, the highly reocmmended unawaited_futures lint requires that you don't just ignore a returned future, and instead wants you to do unawaited(callee()); to signal that it's deliberate. (The unawaited function can be imported from package:meta and will be available from the dart:async library in SDK version 2.14). The unawaited function doesn't handle errors though, so if you can have errors, you should do something more.

You can handle the error locally:

caller() { 
  callee().catchError((e, s) { 
    logErrorSomehow(e, s); 
  }); 
}

(Since null safety, this code only works if the callee() future has a nullable value type. From Dart 2.14, you'll be able to use callee().ignore() instead, until then you can do callee().then((_) => null, onError: (e, s) => logErrorSomehow(e, s)); instead.)

or you can install an error handling zone and run your code in that:

runZoned(() {
  myProgram();
}, onError: logErrorSomehow);

See the runZoned function and it's onError parameter.

Upvotes: 34

Günter Zöchbauer
Günter Zöchbauer

Reputation: 657148

Sure, just omit await. This way callee() is called immediately and when an async operation is called the call will be scheduled in the event queue for later execution and caller() is continued immediately afterwards.

This isn't like a thread though. As mentioned processing is enqueued to the event queue which means it won't be executed until the current task and all previously enqueued tasks are completed.

If you want real parallel execution you need to utilize isolates.

See also

Upvotes: 11

Related Questions