我有一个长时间运行的功能,可以进行一些后台处理。
当功能完成后,我想在短暂延迟后重复。
这样做的最佳方式是什么?
我最终得到了这个混乱的代码
bool busy = false;
new Timer.periodic(const Duration(minutes:1) , (_)async {
if( !busy){
busy = true;
await downloader.download();
busy = false;
}
});
答案 0 :(得分:2)
要在完成后短暂延迟后重复一个功能,你:
我将创建一个单独的函数来执行调用和重新调用,因为它可以更好地分离关注点。
对于第一点,我假设函数在完成后返回Future。然后有很多不同的等待短暂延迟的方法,我将使用最基本的方法Public WriteOnly Shadows Property Enabled() As Boolean
Set(ByVal Value As Boolean)
cbo1.Enabled = Value
cbo2.Enabled = Value
End Set
End Property
,然后通过再次调用该函数重复该过程。
new Timer
如果想要收回错误,可以创造一个新的未来:
Future myFunction() {
// do long operation in background, complete returned future when done.
}
void repeatMyFunction() {
myFunction().then((_) {
// using .then instead of .whenComplete, so we stop in
// case of an error.
new Timer(const Duration(millseconds: shortDelay), repeatMyFunction);
});
}
如果您允许多个错误,并且不想为一个错误停止,则可以将错误作为流返回,并且,将函数结果作为值添加,以便进行良好测量:
Future repeatMyFunction() {
Completer completer = new Completer();
void loop() {
myFunction().then((_) {
// using .then instead of .whenComplete, so we stop in
// case of an error.
new Timer(const Duration(millseconds: shortDelay), loop);
}, onError: completer.completeError);
}
loop();
return completer.future;
}
这些重复方法都没有办法再次阻止它。为此,我将额外的未来传递给repeat函数,并在未来完成时停止。
Stream repeatMyFunction() {
StreamController controller = new StreamController();
void loop() {
myFunction().then(controller.add, onError: controller.addError)
.whenComplete(() {
new Timer(const Duration(millseconds: shortDelay), loop);
}
loop();
return controller.stream;
}
其他变体也可以获得停止 - 未来,并在停止 - 未来完成时完成未来/关闭流。
Günter的建议也很好,而且更简单(但是细粒度控制更少,这是我喜欢的)。您可以使用以下命令将其代码转换为流:
void repeatMyFunction(Future stop) {
bool stopFlag = false;
stop.whenComplete(() { stopFlag = true; });
void loop() {
myFunction().then((_) {
if (!stopFlag) {
new Timer(const Duration(millseconds: shortDelay), loop);
}
});
}
loop();
}
答案 1 :(得分:1)
Future myFunction() async {
await downloader.download();
await new Future.delayed(const Duration(milliseconds:200), myFunction);
}
或避免在上面的代码运行太长时会发生堆栈溢出
Future myFunction() async {
while(true) {
await downloader.download();
await new Future.delayed(const Duration(minutes:1), (){});
}
}