【问题标题】:Why doesn't my Dart async function start working immediately为什么我的 Dart 异步函数不能立即开始工作
【发布时间】:2022-01-10 06:03:29
【问题描述】:

我有这个程序用来学习 Dart 的异步编程。

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
}

输出:

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

在上面的代码中,对于sumStream() 的结果,我选择不立即使用await,因为我想做一些额外的工作,而sumStream() 正忙于从提供的流中消费事件。所以我的期望是sumStream() 会在main() 运行时立即开始运行。我希望输出看起来像下面的文本。我希望文本 working... 与出版商 countStream() 和消费者 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

这是因为 Dart 是单线程的,因此它不能同时运行 main()countStream()sumStream()? 如果是这样,我该如何更改我的程序,以便 sumStream()main() 并行运行(使其成为多线程)?

【问题讨论】:

  • 您不会获得您期望的并发性,因为在事件队列被处理之前不会执行流,并且在您使用await 或退出main 之前不会发生这种情况。是的,每个 Dart 隔离都是单线程的,所以如果你想要并行(而不仅仅是并发)操作,你需要生成一个单独的隔离。
  • @jamesdlin 感谢您的解释。在您的回复和对程序的更多思考之后,我明白为什么它的行为不像我预期的那样。我的问题也不是很清楚,但我想你还是明白了。我真正想要的是在countStream() 处于睡眠状态时运行main(),并在main() 处于睡眠状态时运行countStream()。原来sleep() 阻塞了队列,在我按照下面@mmcdon20 的建议用await Future.delayed(const Duration(milliseconds: 500)); 替换它之后,它就像我喜欢的那样工作。

标签: dart async-await


【解决方案1】:

我很确定这是由于 sleep 函数。 Sleep function documentation:

谨慎使用它,因为当它在睡眠调用中被阻塞时,不能在隔离中处理任何异步操作。

我建议改用这个:

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

这不会阻止正在进行的所有其他异步操作的处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 2023-01-23
    相关资源
    最近更新 更多