Невозможно приостановить изоляцию Dart

Я хотел создать Isolate в Dart, который можно было бы останавливать и возобновлять программно. Это код, который я использовал.

import 'dart:io';
import 'dart:isolate';

void main() async {
  print("Starting isolate");
  Isolate isolate;
  ReceivePort receivePort = ReceivePort();
  isolate = await Isolate.spawn(run, receivePort.sendPort);
  print("pausing");
  Capability cap = isolate.pause(isolate.pauseCapability);
  sleep(Duration(seconds: 5));
  print("Resuming");
  isolate.resume(cap);
}

void run(SendPort sendPort) {
  sleep(Duration(seconds: 2));
  print("Woke up, 1");
  sleep(Duration(seconds: 2));
  print("Woke up, 2");
  sleep(Duration(seconds: 2));
  print("Woke up, 3");
  sleep(Duration(seconds: 2));
  print("Woke up, 4");
  sleep(Duration(seconds: 2));
  print("Woke up, 5");
}

Я получаю отзыв как

Starting isolate
pausing
Woke up, 1
Woke up, 2
Resuming
Woke up, 3
Woke up, 4
Woke up, 5

Но я хочу добиться

Starting isolate
pausing
<--- 5 second delay --->
Resuming
Woke up, 1
Woke up, 2
Woke up, 3
Woke up, 4
Woke up, 5

Но даже после вызова pause () Isolate продолжает работать. Я нашел этот ответ, и он сказал, что это из-за бесконечный цикл в их случае, но я не использую никакого цикла. Так что я здесь делаю не так?


person Ashutosh Singh    schedule 31.05.2020    source источник
comment
Какой у вас результат?   -  person Christopher Moore    schedule 01.06.2020
comment
Я отредактировал вопрос с желаемым и текущим O / P   -  person Ashutosh Singh    schedule 01.06.2020


Ответы (1)


Ваша проблема в том, что вы пропустили деталь в документации для pause на изоляторе:

Когда изолятор получает команду паузы, он прекращает обработку событий из очереди цикла событий. Он по-прежнему может добавлять новые события в очередь в ответ, например, на таймеры или сообщения порта приема. Когда изоляция возобновляется, она начинает обрабатывать уже поставленные в очередь события.

Таким образом, pause не останавливает выполнение метода, а просто гарантирует, что после выполнения текущего запущенного метода он перестанет выполнять дополнительную работу из очереди событий.

Хотя sleep реализован скорее как «остановить все выполнение прямо сейчас в течение N раз ", что больше того, что вы ожидаете:

Используйте это с осторожностью, поскольку в изолированном объекте невозможно обрабатывать асинхронные операции, пока он заблокирован в вызове сна.

Чтобы ваш пример работал, вам нужно заменить sleep вызовы на Future экземпляры, которые вы ожидаете, поскольку это добавит события в очередь событий.

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

Future<void> main() async {
  print("Starting isolate");
  Isolate isolate;
  ReceivePort receivePort = ReceivePort();
  isolate = await Isolate.spawn(run, receivePort.sendPort);
  print("pausing");
  Capability cap = isolate.pause(isolate.pauseCapability);
  sleep(const Duration(seconds: 5));
  print("Resuming");
  isolate.resume(cap);
}

Future<void> run(SendPort sendPort) async {
  await Future<void>.delayed(const Duration(seconds: 2));
  print("Woke up, 1");
  await Future<void>.delayed(const Duration(seconds: 2));
  print("Woke up, 2");
  await Future<void>.delayed(const Duration(seconds: 2));
  print("Woke up, 3");
  await Future<void>.delayed(const Duration(seconds: 2));
  print("Woke up, 4");
  await Future<void>.delayed(const Duration(seconds: 2));
  print("Woke up, 5");
}

Выход:

Starting isolate
pausing
Resuming
Woke up, 1
Woke up, 2
Woke up, 3
Woke up, 4
Woke up, 5
person julemand101    schedule 31.05.2020
comment
Значит ли это, что если внутри метода run() нет ожидаемых фьючерсов, то весь метод run() обрабатывается как отдельное событие очереди? - person Ashutosh Singh; 01.06.2020
comment
да. Если вы не ждете какого-либо будущего (или потока), программа будет просто одним большим событием, которое нельзя приостановить. Поэтому, если вам нужно выполнить тяжелые вычисления и вы хотите иметь возможность приостановить его, вам нужно разделить его на несколько событий или сделать так, чтобы он иногда ждал будущего. Вы можете просто создать пустое будущее и без промедления ждать его, например: await Future<void>.value();. Это вызовет небольшие накладные расходы, поэтому сделайте счетчик, чтобы он делал это только для каждой N итерации. - person julemand101; 01.06.2020