异步Future StreamSubscription错误

时间:2013-05-09 19:45:14

标签: dart

有人可以解释以下代码的错误。我正在调用函数fInputData。第一个工作正常,第二个导致错误: “未处理的异常” “糟糕的状态:Stream已经拥有订阅者”

我需要编写一个输入多个参数的测试控制台程序。

import "dart:async" as async;
import "dart:io"; 

void main() {
  fInputData ("Enter Nr of Iterations : ")
  .then((String sResult){
    int iIters;
    try {
      iIters = int.parse(sResult);
      if (iIters < 0) throw new Exception("Invalid");
    } catch (oError) {
      print ("Invalid entry");
      exit(1);
    }

    print ("In Main : Iterations selected = ${iIters}");

    fInputData("Continue Processing? (Y/N) : ")   // this call bombs
    .then((String sInput){
      if (sInput != "y" && sInput != "Y")
        exit(1);

      fProcessData(iIters);

      print ("Main Completed");
    });
  });
}

async.Future<String> fInputData(String sPrompt) {
  async.Completer<String> oCompleter = new async.Completer(); 

  stdout.write(sPrompt);
  async.Stream<String> oStream = stdin.transform(new StringDecoder());
  async.StreamSubscription oSub;
  oSub = oStream.listen((String sInput) {
    oCompleter.complete(sInput);
    oSub.cancel();
  });
  return oCompleter.future;
}

void fProcessData(int iIters) {
  print ("In fProcessData");
  print ("iIters = ${iIters}");

  for (int iPos = 1; iPos <= iIters; iPos++ ) {
    if (iPos%100 == 0) print ("Processed = ${iPos}");
  }
  print ("In fProcessData - completed ${iIters}");
} 

1 个答案:

答案 0 :(得分:2)

一些background reading

  

Streams有两种形式:单个或多个(也称为   广播)订户。默认情况下,我们的流是单用户   流。这意味着如果您尝试更多地收听流   一次,您将获得异常,并使用任何回调   函数或将来的属性算作听力。

     

您可以将单用户流转换为广播流   使用asBroadcastStream()方法。

所以你有两个选择 - 重新使用一个订阅对象。即调用listen一次,并使订阅对象保持活动状态。

或使用广播流 - 请注意,广播流和单用户流之间存在许多差异,您需要阅读这些内容并确保它们适合您的用例。

以下是重新使用订阅者提出多个问题的示例:

import 'dart:async';
import 'dart:io';

main() {
    var console = new Console();
    var loop;
    loop = () => ask(console).then((_) => loop());
    loop();
}

Future ask(Console console) {
    print('1 + 1 = ...');
    return console.readLine().then((line) {
        print(line.trim() == '2' ? 'Yup!' : 'Nope :(');
    });
}

class Console {
    StreamSubscription<String> _subs;

    Console() {
        var input = stdin
            .transform(new StringDecoder())
            .transform(new LineTransformer());

        _subs = input.listen(null);
    }

    Future<String> readLine() {
        var completer = new Completer<String>();
        _subs.onData(completer.complete);
        return completer.future;
    }
}