0

I have this program that I'm using to learn about Dart's async programming.

import 'dart:io';

Future<int> sumStream(Stream<int> stream) async {
  var sum = 0;
  await for (final value in stream) {
    print('consuming event $value');
    sum += value;
  }
  return sum;
}

Stream<int> countStream(int to) async* {
  for (int i = 1; i <= to; i++) {
    sleep(const Duration(milliseconds: 400));
    print('publishing event $i');
    yield i;
  }
}

Future<void> main() async {
  var stream = countStream(10);
  var sum = sumStream(stream);

  print('working...');
  sleep(const Duration(milliseconds: 500));
  print('working...');
  sleep(const Duration(milliseconds: 500));
  print('working...');
  sleep(const Duration(milliseconds: 500));

  print(await sum); // 55
}

Output:

working...
working...
working...
publishing event 1
consuming event 1
publishing event 2
consuming event 2
publishing event 3
consuming event 3
publishing event 4
consuming event 4
publishing event 5
consuming event 5
publishing event 6
consuming event 6
publishing event 7
consuming event 7
publishing event 8
consuming event 8
publishing event 9
consuming event 9
publishing event 10
consuming event 10
55

In the code above, I chose not to await for the result of sumStream() immediately because I wanted to do some additional work while sumStream() is busy consuming events from the provided stream. So my expectation was that sumStream() would start running immediately while main() is running. I expected the output to look something like below text. I expected the text working... to be interleaved with the other print outs from the publisher countStream() and the consumer sumStream().

working...
publishing event 1
consuming event 1
publishing event 2
consuming event 2
publishing event 3
consuming event 3
working...
publishing event 4
consuming event 4
publishing event 5
consuming event 5
publishing event 6
working...
consuming event 6
publishing event 7
consuming event 7
publishing event 8
consuming event 8
publishing event 9
consuming event 9
publishing event 10
consuming event 10
55

Is this because Dart is single threaded and thus it can't run main(), countStream() and sumStream() at the same time? If so, how could I change my program so that sumStream() would run in parallel with main() (make it multi-threaded)?

2
  • 1
    You don't get the concurrency you expect because the streams won't execute until the event queue is processed, and that won't happen until you use await or exit main. And yes, each Dart isolate is single-threaded, so if you want parallel (and not just concurrent) operations, you will need to spawn a separate isolate. Commented Dec 4, 2021 at 0:07
  • @jamesdlin thanks for the explanation. After your response and thinking about the program a little more, I understand why it was not behaving the way I expected it to. Also my question was not very clear but I guess you understood it anyway. What I really wanted is to run main() while countStream() is sleeping and run countStream() while main() is sleeping. Turns out sleep() was blocking the queue and after I replaced it with await Future.delayed(const Duration(milliseconds: 500)); as suggested by @mmcdon20 below, it's working as I like it to. Commented Dec 4, 2021 at 5:51

1 Answer 1

2

I am pretty sure this is due to the sleep function. Sleep function documentation:

Use this with care, as no asynchronous operations can be processed in a isolate while it is blocked in a sleep call.

I suggest trying this instead:

await Future.delayed(const Duration(milliseconds: 500));

Which won't block the processing of all the other async operations going on.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.