openlang

Isolate.run утащил с собой весь Loader

Вынес большой разбор JSON с главного изолята через Isolate.run и вместо ускорения получил ошибку про объект, который нельзя отправить. Сам разбор был ни при чём, виновато замыкание.

class Loader {
  final updates = StreamController<int>();

  List<Object?> _decode(String text) => jsonDecode(text) as List<Object?>;

  Future<List<Object?>> parse(String text) {
    return Isolate.run(() => _decode(text));
  }
}

_decode - метод экземпляра, поэтому замыкание держит this, а this держит StreamController. Всё, до чего дотягивается замыкание, отправляется в новый изолят, а контроллер отправить нельзя. Сделал _decode статическим, и всё заработало. Чего я так и не понял, так это как заметить такое до запуска. Анализатор к коду выше никаких претензий не имеет.

Разговор продолжается 2

Следуя доводам
  1. Ссылка на ответ

    В сообщении об ошибке есть имя класса, на котором всё споткнулось, и это лучшая подсказка. Если там _StreamController или _AsyncCompleter, а ваша функция с ними не работает, значит что-то в замыкании держит объект, у которого они есть. Я теперь передаю в Isolate.run только функции верхнего уровня или статические, а все значения отдаю аргументами. Неудобно, зато видно в одной строке, что именно уходит в другой изолят.

  2. Ссылка на ответ

    Я бы ещё оставил обновление контроллера на главной стороне. Пусть изолят вернёт разобранный список, а parse после await сам отправит в updates. Тогда фоновая функция остаётся обычной функцией из строки в список, а если позже разбору понадобится сообщать о ходе работы, тогда и решите, нужен ли долгоживущий изолят с портами.

Другие стороны того же вопроса

  1. println внутри функции для swap!

    В документации к swap! сказано, что функция может вызываться несколько раз и не должна иметь побочных эффектов. А в реальном…

    Ответы 1clojure
  2. Пул воркеров после отмены контекста висит на отправке результата

    Наткнулся на простую вещь, но провозился с ней дольше, чем хотелось бы. Пул из восьми воркеров читает задачи из jobs и пишет…

    Ответы 8go
  3. asyncio.TaskGroup, когда один запрос падает

    Сравнение конкурентности в разных языках обычно начинают с синтаксиса. Я бы начал с того, что нужно расчёту, когда что-то пад…

    Ответы 11pythonjuliago