Почему изолят не получает сообщение об остановке?

Пользовательский интерфейс показывает две кнопки: одна кнопка для запуска изоляции, а вторая - для ее остановки в следующий раз. Код UI (виджета) выглядит так:

SendPort sendToIsolatePort;

void _onStartIsolateButtonPushed() async {
  ReceivePort receivePort = ReceivePort();
  receivePort.listen(onMessageReceivedFromIsolate);
  Isolate.spawn(runAsIsolate, receivePort.sendPort);
}

void _onStopIsolateButtonPushed() async {
  sendToIsolatePort.send("Stop");
}

void onMessageReceivedFromIsolate(var message) {
  if (message is String) {
    print("Message received from isolate: " + message);
  } else if (message is SendPort) {
    print("Reply port received");
    sendToIsolatePort = message;
    sendToIsolatePort.send("Hello World?!?");
  }
}

Код в isolate.dart выглядит так: (Примечание: этот код не в виджете или классе, а только в некоторых глобальных функциях)

import 'dart:isolate';

SendPort sendPort;
bool isRunning;

void runAsIsolate(SendPort port) async {
  sendPort = port;
  ReceivePort receivePort = ReceivePort();
  receivePort.listen(onIsolateMessageReceived);

  isRunning = true;
  sendPort.send(receivePort.sendPort);

  while (isRunning) {
    _doSomething();
    _doSomethingMore();
  }

  receivePort.close();
  sendPort.send("Stopped");
  print("Leaving isolate...");
}

void onIsolateMessageReceived(var message) {
  if (message is String) {
    print("Isolate: messate received: " + message);
    if (message == "Stop") {
      isRunning = false;
    }
  } else {
    print("WTFlutter... " + message.toString());
  }
}

void _doSomething() {}
void _doSomethingMore() {}

Теперь по какой-то причине изолят не получает Hello World?!? ни сообщение Stop. У вас есть идеи, почему? А как исправить?

Также: есть ли более простой (или более короткий) способ выполнения потока во флаттере? Изолированный подход и его потоковая связь кажутся слишком сложными для чего-то столь же распространенного, как параллельное выполнение.

Ваш совет очень признателен. Спасибо.


person SePröbläm    schedule 15.01.2021    source источник
comment
насчет выполнения потока: нет, больше ничего нет. изоляты являются фундаментальными строительными блоками флаттера, и в этом заключается их дизайн - нет разделяемой памяти.   -  person ch271828n    schedule 15.01.2021
comment
попробуйте добавить предложение else и напечатать что-нибудь в своем onMessageReceivedFromIsolate для отладки   -  person ch271828n    schedule 15.01.2021
comment
взгляните на: api.flutter.dev/flutter/foundation/compute.html, что является более простым способом выполнять вычисления в другом потоке (изолировать)   -  person ch271828n    schedule 15.01.2021
comment
@ ch271828n Спасибо за вашу помощь! Связь от изолятора до виджета работает нормально (ответный порт (sendToIsolatePort) доставляется через onMessageReceivedFromIsolate()). Проблема возникает при отправке из виджета в изолятор: кажется, что sendToIsolatePort.send() выполняется (в виджете), но onIsolateMessageReceived() не вызывается (в изоляторе). Другими словами: сообщения не доходят до изолятора. Довольно сложно ...   -  person SePröbläm    schedule 15.01.2021
comment
Я вижу проблему: ваш while (isRunning) будет все время тратить в нашем основном изоляторе. таким образом, некогда ваш onIsolateMessageReceived может быть назван! Попробуйте удалить цикл while и сделайте это вместо этого: while(isRunning) await Future.delayed(Duration(seconds: 1));   -  person ch271828n    schedule 16.01.2021
comment
@ ch271828n Да! Вот и все! Большое тебе спасибо!   -  person SePröbläm    schedule 16.01.2021
comment
Пожалуйста! Поскольку это ответ, который решает ваш вопрос, я перефразирую его в ответ ниже. Если вы сочтете это полезным, вы можете проголосовать и принять его :)   -  person ch271828n    schedule 17.01.2021


Ответы (1)


(Перефразировано из комментариев выше, поскольку это ответ, который решает вопрос.)

Я вижу проблему: ваш while (isRunning) будет все время тратить в нашем основном изоляторе. таким образом некогда ваш onIsolateMessageReceived может быть назван! Попробуйте удалить цикл while и сделайте это вместо этого: while(isRunning) await Future.delayed(Duration(seconds: 1));.

Что касается выполнения потока: нет, больше ничего нет. изоляты являются фундаментальными строительными блоками флаттера, и в этом заключается их дизайн - нет разделяемой памяти. Однако есть несколько небольших ярлыков. Например, посмотрите: api.flutter.dev/flutter/foundation/compute.html, который является более простым способом выполнять вычисления в другом потоке (изолировать).

person ch271828n    schedule 17.01.2021