Channel Synchronization in Dart

We can use asynchronous programming in Dart to synchronize execution across different parts of our code. Here’s an example of using a Completer to wait for an asynchronous operation to finish.

import 'dart:async';

// This is the function we'll run asynchronously. The
// Completer will be used to notify when this function's work is done.
Future<void> worker(Completer<void> done) async {
  print('working...');
  await Future.delayed(Duration(seconds: 1));
  print('done');

  // Complete the Future to notify that we're done.
  done.complete();
}

Future<void> main() async {
  // Create a Completer to notify when the work is done.
  final done = Completer<void>();

  // Start an asynchronous worker, giving it the Completer to notify on.
  worker(done);

  // Wait until we receive a notification from the worker via the Completer.
  await done.future;
}

To run the program:

$ dart run channel_synchronization.dart
working...done

In this Dart version:

  1. We use a Completer instead of a channel. The Completer allows us to create a Future that we can complete when we’re ready.

  2. The worker function is now asynchronous. It uses Future.delayed to simulate work being done.

  3. In the main function, we create a Completer and pass it to the worker function.

  4. We use await done.future to wait for the worker to complete its task.

  5. The main function is marked as async and returns a Future<void>.

If you removed the await done.future line from this program, the program would exit before the worker even finished its work.

This pattern is useful when you need to wait for asynchronous operations to complete before proceeding with the rest of your program. For more complex scenarios involving multiple asynchronous tasks, you might consider using Future.wait or other utilities in the dart:async library.