Skip to content

Tasks scheduled through 'SchedulerBinding.instance.scheduleTask' were not executed #82016

Closed

Description

@Nayuta403

Issue

example :https://dartpad.dev/8944b568287269991e5b943accf16861?null_safety=true

I start the animation during initialization and then execute the task . After the animation ends, the task is not executed.

@override
void initState() {
 super.initState();
 animationController = AnimationController(
     vsync: this, duration: Duration(milliseconds: 3000));
 animation = Tween(begin: 1.0, end: 0.0).animate(animationController);
 // start an animation
 animationController.forward();
 // These task will be blocked even if the animation ends
 SchedulerBinding.instance!.scheduleTask(task1, Priority.idle);
 SchedulerBinding.instance!.scheduleTask(task2, Priority.idle);
}

Expected results:

Task1 and Task2 are executed after the animation ends

Actual results:

After the animation ends, the task is not executed.

My point of view:

I notice that task1 and task2 are added to _taskQueue for scheduling here

void _ensureEventLoopCallback() {
assert(!locked);
assert(_taskQueue.isNotEmpty);
if (_hasRequestedAnEventLoopCallback)
return;
_hasRequestedAnEventLoopCallback = true;
Timer.run(_runTasks);
}
// Scheduled by _ensureEventLoopCallback.
void _runTasks() {
_hasRequestedAnEventLoopCallback = false;
if (handleEventLoopCallback())
_ensureEventLoopCallback(); // runs next task when there's time
}

The problem is that once the handleEventLoopCallback() returns false, the _TaskQueue will not be scheduled again until the next scheduleTask.

In this case, because the Priority of the two tasks is Priority.idle, the schedulingStrategy returns false

bool handleEventLoopCallback() {
if (_taskQueue.isEmpty || locked)
return false;
final _TaskEntry<dynamic> entry = _taskQueue.first;
if (schedulingStrategy(priority: entry.priority, scheduler: this)) {
try {
_taskQueue.removeFirst();
entry.run();
} catch (exception, exceptionStack) {

So task1 and task2 are still blocked after the animation ends

I try to modify these method like this :

void _ensureEventLoopCallback() {
  assert(!locked);
  assert(_taskQueue.isNotEmpty);
  if (_hasRequestedAnEventLoopCallback)
    return;
  _hasRequestedAnEventLoopCallback = true;
  print('_ensureEventLoopCallback execute');
  Timer.run(_runTasks);
}
// Scheduled by _ensureEventLoopCallback.
void _runTasks() {
  _hasRequestedAnEventLoopCallback = false;
  if (handleEventLoopCallback())
    _ensureEventLoopCallback();
  else{
    // When the execution fails, determines if the queue is empty
    if(_taskQueue.isNotEmpty){
      // When the task queue is not empty, the judgment is made again
      _ensureEventLoopCallback();
    }
  } // runs next task when there's time
}

When the task queue is not empty, the judgment is made again, just like Event loop

In the above example, tasks 1 and 2 were successfully executed after the animation ended

However, through logging, I found that _ensureEventLoopCallback() was called too frequently. Because the Timer.run will continue to add tasks to the isolate while the _taskQueue is not empty

However, I don't think this is necessary, because the result of the schedulingStrategy will not change until the next frame is drawn

So i modify _ensureEventLoopCallback() like this:

// Ensures that the scheduler services a task scheduled by [scheduleTask].
void _ensureEventLoopCallback() async{
  assert(!locked);
  assert(_taskQueue.isNotEmpty);
  if (_hasRequestedAnEventLoopCallback)
    return;
  _hasRequestedAnEventLoopCallback = true;
  print('_ensureEventLoopCallback execute');
  // Executes after each frame is rendered
  await endOfFrame;
  _runTasks();
}

At the end of each frame, the _taskQueue is scheduled .

And tasks 1 and 2 were also successfully executed after the animation ended

What do you think, if this change is necessary, I can PR to fix it

[✓] Flutter (Channel stable, 2.0.6, on macOS 11.2.2 20D80 darwin-x64, locale zh-Hans-CN)
    • Flutter version 2.0.6 at /Users/nayuta/Desktop/fsdk/flutter2.0
    • Framework revision 1d9032c7e1 (7 days ago), 2021-04-29 17:37:58 -0700
    • Engine revision 05e680e202
    • Dart version 2.12.3
    • Pub download mirror http://pub.ke.com
    • Flutter download mirror https://storage.flutter-io.cn

Activity

  1. darshankawar commented on May 7, 2021

    @darshankawar
    Member
    flutter doctor -v
    
    [✓] Flutter (Channel stable, 2.0.6, on Mac OS X 10.15.4 19E2269 darwin-x64,
        locale en-GB)
        • Flutter version 2.0.6 at /Users/dhs/documents/fluttersdk/flutter
        • Framework revision 1d9032c7e1 (7 days ago), 2021-04-29 17:37:58 -0700
        • Engine revision 05e680e202
        • Dart version 2.12.3
    
    [!] Xcode - develop for iOS and macOS
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Xcode 12.3, Build version 12C33
        ! CocoaPods 1.9.3 out of date (1.10.0 is recommended).
            CocoaPods is used to retrieve the iOS and macOS platform side's plugin
            code that responds to your plugin usage on the Dart side.
            Without CocoaPods, plugins will not work on iOS or macOS.
            For more info, see https://flutter.dev/platform-plugins
          To upgrade see
          https://guides.cocoapods.org/using/getting-started.html#installation for
          instructions.
    
    [✓] Chrome - develop for the web
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] VS Code (version 1.55.2)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.21.0
    
    [✓] Connected device (3 available)
        • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios
          • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator)
        • macOS (desktop)            • macos                                •
          darwin-x64     • Mac OS X 10.15.4 19E2269 darwin-x64
        • Chrome (web)               • chrome                               •
          web-javascript • Google Chrome 90.0.4430.93
    
    ! Doctor found issues in 1 category.
    
    [✓] Flutter (Channel master, 2.3.0-1.0.pre.242, on Mac OS X 10.15.4 19E2269
        darwin-x64, locale en-GB)
        • Flutter version 2.3.0-1.0.pre.242 at
          /Users/dhs/documents/fluttersdk/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 3ab799bbc9 (2 hours ago), 2021-05-06 19:49:02 -0700
        • Engine revision f57e986aa8
        • Dart version 2.14.0 (build 2.14.0-74.0.dev)
    
    [!] Xcode - develop for iOS and macOS
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Xcode 12.3, Build version 12C33
        ! CocoaPods 1.9.3 out of date (1.10.0 is recommended).
            CocoaPods is used to retrieve the iOS and macOS platform side's plugin
            code that responds to your plugin usage on the Dart side.
            Without CocoaPods, plugins will not work on iOS or macOS.
            For more info, see https://flutter.dev/platform-plugins
          To upgrade see
          https://guides.cocoapods.org/using/getting-started.html#installation for
          instructions.
    
    [✓] Chrome - develop for the web
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] VS Code (version 1.55.2)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.21.0
    
    [✓] Connected device (2 available)
        • macOS (desktop) • macos  • darwin-x64     • Mac OS X 10.15.4 19E2269
          darwin-x64
        • Chrome (web)    • chrome • web-javascript • Google Chrome 90.0.4430.93
    
    ! Doctor found issues in 1 category.
    dhs@Dhss-MacBook-Pro ~ % 
    
    
  2. added
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    frameworkflutter/packages/flutter repository. See also f: labels.
    and removed
    in triagePresently being triaged by the triage team
    on May 7, 2021
  3. Hixie commented on May 7, 2021

    @Hixie
    Contributor
  4. goderbauer commented on May 10, 2021

    @goderbauer
    Member

    It does look like a bug that the tasks do not run until another task is scheduled. Happy to look at a PR to fix the problem.

  5. Nayuta403 commented on May 11, 2021

    @Nayuta403
    ContributorAuthor

    It does look like a bug that the tasks do not run until another task is scheduled. Happy to look at a PR to fix the problem.

    OK I will fix it

  6. added
    P2Important issues not at the top of the work list
    on Apr 27, 2022
  7. exaby73 commented on May 4, 2022

    @exaby73
    Member

    Tested on current stable and master, issue still persists (see attached video).

    Code sample
    Code example used (same as one provided in DartPad by OP)
    import 'package:flutter/material.dart';
    import 'package:flutter/scheduler.dart';
    
    void main() => runApp(const MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({Key? key, this.title}) : super(key: key);
      final String? title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
      late AnimationController animationController;
      late Animation<double> animation;
    
      String title = 'init';
    
      void task1() {
        setState(() {
          print('task 1 execute');
          title = 'task1';
        });
      }
    
      void task2() {
        setState(() {
          print('task 2 execute');
          title = 'task2';
        });
      }
    
      @override
      void initState() {
        super.initState();
        animationController = AnimationController(
            vsync: this, duration: const Duration(milliseconds: 3000));
        animation = Tween(begin: 1.0, end: 0.0).animate(animationController);
        // start an animation
        animationController.forward();
        // These task will be blocked even if the animation ends
        SchedulerBinding.instance.scheduleTask(task1, Priority.idle);
        SchedulerBinding.instance.scheduleTask(task2, Priority.idle);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title!),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(title),
                FadeTransition(
                    opacity: animation,
                    child: Container(
                      width: 100.0,
                      height: 100.0,
                      decoration: const BoxDecoration(
                        color: Colors.red,
                      ),
                    ))
              ],
            ),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }

    Some more insights on this, I have tried scheduling another task using scheduleTask after 5 seconds of delay, 2 seconds after the animation stops, switching between all available Prioritys, but neither the first 2 nor the last one in the Future was executed. See the modified code.

    Modified code
      @override
      void initState() {
        super.initState();
        animationController = AnimationController(
            vsync: this, duration: const Duration(milliseconds: 3000));
        animation = Tween(begin: 1.0, end: 0.0).animate(animationController);
        // start an animation
        animationController.forward();
        // These task will be blocked even if the animation ends
        SchedulerBinding.instance.scheduleTask(task1, Priority.idle);
        SchedulerBinding.instance.scheduleTask(task2, Priority.idle);
    
        Future.delayed(
          const Duration(seconds: 5),
          () {
            print('future executed');
            setState(() {
              title = 'future';
              SchedulerBinding.instance.scheduleTask(
                () => print('scheduled (future)'),
                Priority.idle,
              );
            });
          },
        );
      }
    Video
    82016_stable_ios.mov
    flutter doctor -v
    [✓] Flutter (Channel master, 2.13.0-0.0.pre.886, on macOS 12.3.1 21E258 darwin-arm, locale en-US)
        • Flutter version 2.13.0-0.0.pre.886 at /Users/nabeelparkar/fvm/versions/master
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision e9c0ee1e08 (7 hours ago), 2022-05-04 00:29:07 -0400
        • Engine revision 0b46116471
        • Dart version 2.18.0 (build 2.18.0-82.0.dev)
        • DevTools version 2.12.2
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0-rc1)
        • Android SDK at /Users/nabeelparkar/Library/Android/sdk/
        • Platform android-32, build-tools 32.0.0-rc1
        • ANDROID_SDK_ROOT = /Users/nabeelparkar/Library/Android/sdk/
        • Java binary at: /opt/homebrew/opt/openjdk@11/bin/java
        • Java version OpenJDK Runtime Environment Homebrew (build 11.0.15+0)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 13.3.1)
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • CocoaPods version 1.11.3
    
    [✓] Chrome - develop for the web
        • CHROME_EXECUTABLE = /Applications/Brave Browser.app/Contents/MacOS/Brave Browser
    
    [!] Android Studio (not installed)
        • Android Studio not found; download from https://developer.android.com/studio/index.html
          (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
    
    [✓] IntelliJ IDEA Ultimate Edition (version 2022.1)
        • IntelliJ at /Applications/IntelliJ IDEA.app
        • Flutter plugin version 67.0.4
        • Dart plugin version 221.5588
    
    [✓] VS Code (version 1.66.2)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.40.0
    
    [✓] Connected device (3 available)
        • iPhone 13 Pro Max (mobile) • F9E7F1F9-285A-4DE8-94CD-78FE97310572 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-15-4 (simulator)
        • macOS (desktop)            • macos                                • darwin-arm64   • macOS 12.3.1 21E258 darwin-arm
        • Chrome (web)               • chrome                               • web-javascript • Brave Browser 101.1.38.111
    
    [✓] HTTP Host Availability
        • All required HTTP hosts are available
    
    ! Doctor found issues in 1 category.
    
  8. Nayuta403 commented on May 13, 2022

    @Nayuta403
    ContributorAuthor

    Yeah I plan to reopen PR this month @exaby73

  9. AsturaPhoenix commented on Dec 2, 2022

    @AsturaPhoenix

    Here's another take on this PR, which services the tasks as a post-frame callback rather than on the timer queue, and attempts to address the testing concerns using zoned timers and cleaning up after one of the earlier tests:

    #116422

  10. danagbemava-nc commented on Jul 3, 2024

    @danagbemava-nc
    Member

    Closing this as fixed in #151168

  11. added
    r: fixedIssue is closed as already fixed in a newer version
    on Jul 3, 2024
  12. github-actions commented on Jul 17, 2024

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  13. locked as resolved and limited conversation to collaborators on Jul 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: animationAnimation APIsfound in release: 2.10Found to occur in 2.10found in release: 2.13Found to occur in 2.13frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions