当隔离被杀死时,抖动隔离内的计时器不会停止
Timer inside flutter isolate not stopping when isolate is killed
我有一个应用程序使用 API 调用将操纵杆位置数据上传到网络服务器。
移动操纵杆时会调用此方法。如果操纵杆不在中心,它会停止任何先前的 运行 隔离并启动新的隔离。
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方法(isolate中的方法):
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);
});
}
问题在于 uploadJoystickPosition 不断上传操纵杆的旧位置和新位置。我假设这是因为计时器保持 运行 即使隔离被杀死。
问题:
- 为什么我的计时器在我杀死隔离后仍继续运行(并上传)?
- 当我杀死其 运行 中的隔离物时,如何让我的计时器停止?
正如我在评论中指出的那样,您的示例代码具有:
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
被调用。因此,你的问题不是杀死一个 isolate 并不能阻止它的 Timer
s,而是你 leak isolates 并阻止你自己杀死它们。您需要添加一个守卫,以避免在另一个创建请求正在进行时产生一个新的隔离。 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,它提供了一种简单的方法来使用 isolates 和已经完成的安全检查和其他很酷的功能,还有一个很好解释的文档。
我有一个应用程序使用 API 调用将操纵杆位置数据上传到网络服务器。
移动操纵杆时会调用此方法。如果操纵杆不在中心,它会停止任何先前的 运行 隔离并启动新的隔离。
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方法(isolate中的方法):
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);
});
}
问题在于 uploadJoystickPosition 不断上传操纵杆的旧位置和新位置。我假设这是因为计时器保持 运行 即使隔离被杀死。
问题:
- 为什么我的计时器在我杀死隔离后仍继续运行(并上传)?
- 当我杀死其 运行 中的隔离物时,如何让我的计时器停止?
正如我在评论中指出的那样,您的示例代码具有:
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
被调用。因此,你的问题不是杀死一个 isolate 并不能阻止它的 Timer
s,而是你 leak isolates 并阻止你自己杀死它们。您需要添加一个守卫,以避免在另一个创建请求正在进行时产生一个新的隔离。 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,它提供了一种简单的方法来使用 isolates 和已经完成的安全检查和其他很酷的功能,还有一个很好解释的文档。