Skip to content

On hot restart, the main thread and isolated threads will cause devtools to show a paused state #61092

@maxfrees

Description

@maxfrees
Cursor_nR5LmfCzWw.mp4

Each time, it needs to be clicked twice to restore before it can run normally. Is there any way to solve this problem

[!] Flutter (Channel stable, 3.32.0, on Microsoft Windows [ 10.0.19045.5854], locale zh-CN) [923ms]
• Flutter version 3.32.0 on channel stable at E:\flutter\default
! Warning: flutter on your path resolves to E:\flutter\versions\stable\bin\flutter, which is not inside your
current Flutter SDK checkout at E:\flutter\default. Consider adding E:\flutter\default\bin to the front of your
path.
! Warning: dart on your path resolves to E:\flutter\versions\stable\bin\dart, which is not inside your current
Flutter SDK checkout at E:\flutter\default. Consider adding E:\flutter\default\bin to the front of your path.
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision be698c48a6 (2 days ago), 2025-05-19 12:59:14 -0700
• Engine revision 1881800949
• Dart version 3.8.0
• DevTools version 2.45.1
• Pub download mirror https://pub.flutter-io.cn/
• Flutter download mirror https://storage.flutter-io.cn/
• If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly
to perform update checks and upgrades.
import 'dart:isolate';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Isolate Demo',
      theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple)),
      home: const MyHomePage(title: 'Flutter Isolate Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class IsolateMessage {
  final int value;
  final SendPort responsePort;

  IsolateMessage(this.value, this.responsePort);
}

class _MyHomePageState extends State<MyHomePage> {
  final int _counter = 0;
  String _isolateResult = "No result yet";
  bool _isCalculating = false;
  int _inputValue = 1000000;

  ReceivePort? _receivePort;
  Isolate? _isolate;
  SendPort? _isolateSendPort;

  void _startHeavyTask() async {
    if (_isCalculating) return;

    setState(() {
      _isCalculating = true;
      _isolateResult = "..";
    });

    _receivePort = ReceivePort();

    _isolate = await Isolate.spawn(_isolateEntryPoint, _receivePort!.sendPort);

    _receivePort!.listen((message) {
      if (message is SendPort) {
        _isolateSendPort = message;
        _sendMessageToIsolate();
      } else {
        setState(() {
          _isolateResult = "message: $message";
          _isCalculating = false;
        });
        _cleanupIsolate();
      }
    });
  }

 
  void _sendMessageToIsolate() {
    if (_isolateSendPort != null) {
      final responsePort = ReceivePort();

      _isolateSendPort!.send(IsolateMessage(_inputValue, responsePort.sendPort));

      responsePort.listen((message) {
        setState(() {
          _isolateResult = "s: $message";
        });
        responsePort.close();
      });
    }
  }

  void _cleanupIsolate() {
    _isolate?.kill(priority: Isolate.immediate);
    _isolate = null;
    _receivePort?.close();
    _receivePort = null;
    _isolateSendPort = null;
  }

  static void _isolateEntryPoint(SendPort mainSendPort) {
    final receivePort = ReceivePort();

    mainSendPort.send(receivePort.sendPort);

    receivePort.listen((message) {
      if (message is IsolateMessage) {
        int limit = message.value;

        message.responsePort.send("limit: $limit");

        int sum = 0;
        for (int i = 0; i < limit; i++) {
          sum += i;
        }

        mainSendPort.send(sum);
      }
    });
  }

  @override
  void dispose() {
    _cleanupIsolate();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title)),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text('demo:'),
            Text('$_counter', style: Theme.of(context).textTheme.headlineMedium),
            const SizedBox(height: 30),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 50),
              child: TextField(
                keyboardType: TextInputType.number,
                onChanged: (value) {
                  if (value.isNotEmpty) {
                    _inputValue = int.tryParse(value) ?? 1000000;
                  }
                },
              ),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _isCalculating ? null : _startHeavyTask,
              child: Text(_isCalculating ? 'send...' : 'send'),
            ),
            const SizedBox(height: 20),
            Text(_isolateResult),
          ],
        ),
      ),
    );
  }
}

Cursor_RQccLfRXb3.mp4

If the code contains an isolation thread,
Each time a hot restart is performed and the "Send Isolation Thread Message" is clicked, there is a probability that the thread will be in a paused state, blocking the code execution. It is necessary to manually click "Start" for it to execute.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-devexpFor issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions