0

I want to use dart isolates in Flutter. When I use it in a StatelessWidget it works fine, but when I change the widget to StatefulWidget, it gives me the following error:

E/flutter ( 3154): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception:
Invalid argument(s): Illegal argument in isolate message: (object extends NativeWrapper - Library:'dart:ui' Class: EngineLayer)
E/flutter ( 3154): #0      Isolate._spawnFunction (dart:isolate-patch/isolate_patch.dart:399:25)
E/flutter ( 3154): #1      Isolate.spawn (dart:isolate-patch/isolate_patch.dart:379:7)
E/flutter ( 3154): #2      _TestScreenState.createIsolate test_screen.dart:18
E/flutter ( 3154): #3      _TestScreenState.build.<anonymous closure> test_screen.dart:38
E/flutter ( 3154): #4      _InkResponseState.handleTap ink_well.dart:1096
E/flutter ( 3154): #5      GestureRecognizer.invokeCallback recognizer.dart:253
E/flutter ( 3154): #6      TapGestureRecognizer.handleTapUp tap.dart:627
E/flutter ( 3154): #7      BaseTapGestureRecognizer._checkUp tap.dart:306
E/flutter ( 3154): #8      BaseTapGestureRecognizer.handlePrimaryPointer tap.dart:239
E/flutter ( 3154): #9      PrimaryPointerGestureRecognizer.handleEvent recognizer.dart:615
E/flutter ( 3154): #10     PointerRouter._dispatch pointer_router.dart:98
E/flutter ( 3154): #11     PointerRouter._dispatchEventToRoutes.<anonymous closure> pointer_router.dart:143
E/flutter ( 3154): #12     _LinkedHashMapMixin.forEach (dart:collection patch/compact_hash.dart:625:13)
E/flutter ( 3154): #13     PointerRouter._dispatchEventToRoutes
E/flutter ( 3154): #14     PointerRouter.route
pointer_router.dart:127
E/flutter ( 3154): #15     GestureBinding.handleEvent
binding.dart:460
E/flutter ( 3154): #16     GestureBinding.dispatchEvent
binding.dart:440
E/flutter ( 3154): #17     RendererBinding.dispatchEvent
binding.dart:336
E/flutter ( 3154): #18     GestureBinding._handlePointerEventImmediately
binding.dart:395
E/flutter ( 3154): #19     GestureBinding.handlePointerEvent
binding.dart:357
E/flutter ( 3154): #20     GestureBinding._flushPointerEventQueue
binding.dart:314
E/flutter ( 3154): #21     GestureBinding._handlePointerDataPacket
binding.dart:295
E/flutter ( 3154): #22     _invoke1 (dart:ui/hooks.dart:164:13)
E/flutter ( 3154): #23     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:361:7)
E/flutter ( 3154): #24     _dispatchPointerDataPacket (dart:ui/hooks.dart:91:31)

My code is as follows:

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

import 'package:flutter/material.dart';

class TestScreen extends StatefulWidget {
  const TestScreen({super.key});

  @override
  State<TestScreen> createState() => _TestScreenState();
}

class _TestScreenState extends State<TestScreen> {

  void createIsolate() async {
    print('Inside createIsolate');
    final p = ReceivePort();
    await Isolate.spawn(_createIsolate, p.sendPort);

    print(await p
        .takeWhile((element) => element is String)
        .take(1)
        .cast<String>()
        .first);
  }

  Future<void> _createIsolate(SendPort p) async {
    print('Spawned isolate started.');
    p.send('This is the message!');
    Isolate.exit();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => createIsolate(),
          child: const Text('Create isolate'),
        ),
      ),
    );
  }
}

The error specifically points to await Isolate.spawn(_createIsolate, p.sendPort); line. But when I change the TestScreen widget to a StatelessWidget, then there is no error and the output is as follows:

I/flutter ( 3154): Inside createIsolate
I/flutter ( 3154): Spawned isolate started.
I/flutter ( 3154): This is the message!

What is the problem here and how can we solve it? I need the widget to be StatefullWidget, specifically, I use the isolate in the initState method. Thanks in advance for your help.

sm_sayedi
  • 326
  • 2
  • 17
  • SendPort is limited. It looks like you're trying to send UI elements through to a thread. That'll never work. Send a computation there. And use Isolate.run - far simpler interface. – Randal Schwartz Apr 09 '23 at 18:16
  • @RandalSchwartz I didn't send the UI elements through isolate, in the `spawn()` method of `Isolate`, I sent the `SendPort`, and in the `send()` method of `SendPort`, I sent a `String`. This same code works fine if the `TestScreen` widget is changed to `StatelessWidget`. – sm_sayedi Apr 10 '23 at 04:15
  • 1
    If you make `_createIsolate` either a top-level function or a static function it should solve this error. The problem is that methods capture the variables in scope which would include properties in the `State<>` class that you are extending. Those variables are being implicitly passed along with the method and some variables are not allowed to be sent over an isolate, presumably `State<>` includes at least one property that cannot be sent over, thus causing the error. – mmcdon20 Apr 24 '23 at 15:26

0 Answers0