当隔离被终止时,颤动隔离内的计时器未停止



我有一个应用程序使用API调用将操纵杆位置数据上传到Web服务器。

移动操纵杆时会调用此方法。如果操纵手柄不在中间,它会停止任何以前运行的隔离,并启动新的隔离。

void onJoystickMoved(double angle, double distance) {
stopIsolate();
if(distance > 0.06){
startIsolate(JoystickPosition.fromDistanceAndRadius(distance, angle));
}
}

隔离启动和停止方法

Future<void> startIsolate(JoystickPosition position) async {
isolate = await Isolate.spawn(uploadJoystickPosition, position);
}
void stopIsolate() {
if (isolate != null) {
debugPrint("Stopping isolate");
isolate.kill();
isolate = null;
}
}

uploadJoystickPosition方法(隔离中的方法(:

void uploadJoystickPosition(JoystickPosition position){
Timer.periodic(new Duration(seconds: 1), (Timer t) {
DataModel dataModel = DataModel(1, getTimeInSeconds());
dataModel.joystickPosition = position;
debugPrint("Distance: ${position.distance}");
uploadData(dataModel).then(uploadResponse, onError: uploadError);
});
}

问题是上传的操纵杆位置一直在上传操纵杆的旧位置和新位置。我想这是因为即使隔离被杀死,计时器也会一直运行。

问题:

  1. 为什么在我杀死隔离后,我的计时器仍在运行(并上传(
  2. 当我杀死正在运行的隔离区时,我如何让计时器停止

正如我在评论中所指出的,您的示例代码有:

Future<void> startIsolate() async {
stopIsolate();
isolate =
await Isolate.spawn(isolateMethod, DateTime.now().toIso8601String());
}
void stopIsolate() {
if (isolate != null) {
debugPrint("Stopping isolate");
isolate.kill();
isolate = null;
}
}

当对startIsolate的另一个调用已经在进行时,没有任何东西可以阻止调用startIsolate。因此,你的问题不是杀死一个隔离物并不能阻止其Timer,而是你泄漏隔离物并阻止自己杀死它们。您需要添加一个保护,以避免在另一个创建请求进行时生成新的隔离。bool就足够了:

bool isStartingIsolate = false;
Future<void> startIsolate() async {
if (isStartingIsolate) {
// An isolate is already being spawned; no need to do anything.
return;
}
stopIsolate();
isStartingIsolate = true;
try {
isolate =
await Isolate.spawn(isolateMethod, DateTime.now().toIso8601String());
} finally {
isStartingIsolate = false;
}
}

另一种方法是,如果您想等待挂起的startIsolate调用完成,然后再处理任何新调用:

Future<void> pendingStartIsolate;
Future<void> startIsolate() async {
while (pendingStartIsolate != null) {
await pendingStartIsolate;
}
stopIsolate();
try {
pendingStartIsolate =
Isolate.spawn(isolateMethod, DateTime.now().toIso8601String());
isolate = await pendingStartIsolate;
} finally {
pendingStartIsolate = null;
}
}

查看插件easy_isolate,它提供了一种简单的使用隔离的方法,具有已经完成的安全检查和其他很酷的功能,还提供了一个解释良好的文档。

https://pub.dev/packages/easy_isolate

最新更新