有人可以解释以下代码的错误。我正在调用函数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}");
}
答案 0 :(得分:2)
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;
}
}