【问题标题】:Dart program exits without executing last statementDart 程序退出而不执行最后一条语句
【发布时间】:2019-10-03 18:53:37
【问题描述】:

我正在尝试了解 Streams 并编写了一些代码。 一切似乎都正常,程序以状态码 0 退出。但是它不打印“循环完成”和“主要完成”字符串。我不知道为什么。

import 'dart:async';

Stream<int> countStream(int to) async* {
      for (int i = 1; i <= to; i++) {
              yield i;
      }
}

class Retry {
    StreamController<int> _outgoing;

    Retry(Stream<int> incoming) {
        _outgoing = StreamController<int>();
        _outgoing.addStream(incoming);
    }

    Future<void> process() async {
        await for (final i in _outgoing.stream) {
            print("got $i");
        }
        print('loop done'); // Not printed
    }
}

void main() async {
  var stream = countStream(4);
  var retry = Retry(stream);
  await retry.process();
  print('main done'); // Not printed
}

【问题讨论】:

  • 它没有解释,但我注意到删除 main 中的 async(以及 retry.process() 中的 await)使其按预期工作。所以它可能与异步函数在后台的实现方式有关。无论如何,这对我来说看起来非常奇怪。
  • 如果您将_outgoing 设为Stream&lt;int&gt; 而不是StreamController,它也可以工作。
  • 这可能是因为流永远不会关闭,所以它一直在等待一个值,尝试在 Retry 构造函数的末尾添加 Timer(Duration(seconds: 10), () =&gt; _outgoing.close()); ,你会在 10 秒内看到消息将被打印

标签: dart stream


【解决方案1】:

_outgoing.stream 永远不会关闭,因此await for 之后的代码永远不会执行。 VM 确实注意到该流上也不会有任何 new 事件,因此不会发生任何其他事情,它可以退出。您可以通过以下方式修复该错误:

_outgoing.addStream(incoming).whenComplete(() {
    _outgoing.close();
});

【讨论】:

  • 这对于虚拟机来说听起来很糟糕。
  • s/cleaver/clever(我不是很聪明)
  • VM 很“聪明”,因为它有一个事件队列,当该事件队列为空,并且没有可用的输入端口或活动计时器剩余时,可以向事件队列添加任何内容,然后它就停止了。您的代码是这样编写的,因此在某些时候,队列中不再有事件。当countStream 流完成时会发生这种情况。有代码等待事件,但没有安排剩余的可以创建这些事件的代码。然后虚拟机关闭。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-06
  • 2014-07-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多