【问题标题】:In Dart, why waiting for a trivial ("empty") StreamController stream immediately exits program?在 Dart 中,为什么要等待一个微不足道的(“空”)StreamController 流立即退出程序?
【发布时间】:2020-08-25 10:13:06
【问题描述】:

这是一个简单程序的主干,它使用 StreamController 监听某些输入流并在其自己的流上输出一些其他数据作为响应:

import 'dart:async';     

main() async {     
    var c = StreamController(         
            onListen: (){},         
            onPause: (){},         
            onResume: (){},         
            onCancel: (){});         

    print("start");         
    await for (var data in c.stream) {         
            print("loop");         
    }         

    print("after loop");         
}     

输出:

$ dart cont.dart
start
$ dart

为什么这段代码在没有执行 print("loop") 和 print("after loop") 的情况下直接在 await for 行退出?

注意:在原始程序中,onListen() 将接收输入流并订阅它。循环实际上一直在工作,直到在输入流上调用 subscription.cancel(),当它也突然退出时,没有任何机会清理。

【问题讨论】:

    标签: dart async-await


    【解决方案1】:

    我对此感到惊讶,但是所有async/await 代码再次转换为.then()s,似乎所有内容都无法完美翻译。

    这似乎是答案的一部分:您需要在另一个任务中关闭流才能离开await forHere 是以前的相关问题。由于我们不关闭它,await for 之后的行不会执行。这是一个避免这种情况的示例:

    import 'dart:async';
    
    main() async {
      var c = StreamController(
          onListen: () {},
          onPause: () {},
          onResume: () {},
          onCancel: () {});
    
      print("start");
      await Future.wait(<Future>[producer(c), consumer(c)]);
    
      print("after loop");
    }
    
    Future producer(StreamController c) async {
      // this makes it print "loop" as well
      // c.add("val!"); 
      await c.close();
    }
    
    Future consumer(StreamController c) async {
      await for (var data in c.stream) {
        print("loop");
      }
    }
    

    哪个打印:

    start
    after loop
    

    所以,故事的寓意是,

    1. 永远不要让 StreamController 无人看管,否则会发生奇怪的事情。
    2. 您等待的一些异步函数会破坏您的代码,甚至绕过您的 try/finally 块!

    我以为我对 async/await 了如指掌,但第二点现在让我害怕了。

    【讨论】:

    • 好的,但是为什么呢?我的应用程序会突然在用户面前退出吗?什么时候?
    • 我不这么认为。请注意,在您使用小部件调用 runApp() 之前,它还不是 Flutter。既然你没有在那里等待任何东西,那应该没问题。我认为runApp() 在某处有某种while(true) 作为其事件循环。我认为这仅意味着您调用的异步函数可能会奇怪地终止。该应用程序将保持正常。
    • 再想一想,这里唯一的问题是主函数返回和应用程序因此而退出。带有一些.then() 调用的函数返回相同的结果。 .then()s 是否提前。在这种情况下,他们不会前进。因此,在 Flutter 场景中,它就像任何其他从未完成的 async 函数一样。
    猜你喜欢
    • 2015-02-24
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 2021-04-21
    • 1970-01-01
    相关资源
    最近更新 更多