Coder Social home page Coder Social logo

machinescream / worker_manager Goto Github PK

View Code? Open in Web Editor NEW
313.0 7.0 29.0 628 KB

Effective cpu intensive function scheduling across isolates, true canceling capability

License: MIT License

Dart 95.30% Kotlin 1.25% Swift 1.40% Objective-C 0.13% Shell 1.93%

worker_manager's Introduction

Worker Manager

Worker Manager is a powerful and easy-to-use library that helps you efficiently manage CPU-intensive tasks in your Flutter applications. It offers several advantages over traditional async programming or the built-in compute method. Note that the functions you are passing should either be static methods, globally defined functions or lambdas to ensure they are accessible from other isolates.

New Feature - dynamicSpawn flag in init

By using this flag, worker_manager changes its behavior regarding isolate management. If this flag is set to true, new isolates will be spawned only if necessary and killed when they are no longer needed.

Advantages

Efficient Scheduling

This library schedules CPU-intensive functions to avoid skipping frames or freezes in your Flutter application. It ensures that your app runs smoothly, even when dealing with heavy computations.

Reusable Isolates

Unlike the compute method, which always creates a new Dart isolate, Worker Manager reuses existing isolates. This approach is more efficient and prevents overloading the CPU. When resources are not freed up, using the compute method may cause freezes and skipped frames.

Cancelable Tasks

Worker Manager provides a cancellation functionality through the Cancelable class and its cancel method. This feature allows developers to free up resources when they are no longer needed, improving the app's performance and responsiveness.

Gentle Cancellation

In addition to the standard cancellation method, Worker Manager offers a more gentle approach to cancellation. This new feature, executeGentle, does not immediately terminate the Dart isolate but instead provides a lambda function that can be called periodically within the task to check if it should be cancelled. This allows tasks to clean up and terminate gracefully.

Inter-Isolate Communication

The library supports communication between isolates with the executeWithPort method. This feature enables sending progress messages or other updates between isolates, providing more control over your tasks.

Gentle Cancellation with Port

The executeGentleWithPort method is another valuable feature of Worker Manager that combines gentle cancellation and inter-isolate communication. It accepts two arguments: a port for inter-isolate communication and a getter function isCancelled for gentle cancellation. This offers more flexibility and control, allowing tasks to communicate with other isolates while also providing an opportunity for graceful termination.

Usage

Execute the task

Cancelable<ResultType> cancelable = workerManager.execute<ResultType>(
  () async {
    // Your CPU-intensive function here
  },
  priority: WorkPriority.immediately,
);

Execute a Task with Gentle Cancellation

Cancelable<ResultType> cancelable = workerManager.executeGentle<ResultType>(
  (isCanceled) async {
    while (!isCanceled()) {
      // Your CPU-intensive function here
      // Check isCanceled() periodically to decide whether to continue or break the loop
    }
  },
  priority: WorkPriority.immediately,
);

Execute a Task with Inter-Isolate Communication

Cancelable<ResultType> cancelable = workerManager.executeWithPort<ResultType, MessageType>(
  (SendPort sendPort) async {
    // Your CPU-intensive function here
    // Use sendPort.send(message) to communicate with the main isolate
  },
  onMessage: (MessageType message) {
    // Handle the received message in the main isolate
  },
);

Execute a Task with Gentle Cancellation and Inter-Isolate Communication

Cancelable<ResultType> cancelable = workerManager.executeGentleWithPort<ResultType, MessageType>(
  (SendPort sendPort, IsCanceled isCanceled) async {
    while (!isCanceled()) {
      // Your CPU-intensive function here
      // Use sendPort.send(message) to communicate with the main isolate
      // Check isCanceled() periodically to decide whether to continue or break the loop
    }
  },
  onMessage: (MessageType message) {
    // Handle the

 received message in the main isolate
  },
  priority: WorkPriority.immediately,
);

Cancel a Task

cancelable.cancel();

Dispose Worker Manager

await workerManager.dispose();

Conclusion

By using Worker Manager, you can enjoy the benefits of efficient task scheduling, reusable isolates, cancellable tasks, and inter-isolate communication. It provides a clear advantage over traditional async programming and the built-in compute method, ensuring that your Flutter applications remain performant and responsive even when handling CPU-intensive tasks. The additional executeGentleWithPort feature provides both gentle cancellation and inter-isolate communication for your tasks, offering further control and efficiency.

worker_manager's People

Contributors

dab246 avatar emakar avatar festelo avatar galunecandrey avatar machinescream avatar mack-at-pieces avatar moazelsawaf avatar narumi147 avatar srix55 avatar victoruvarov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

worker_manager's Issues

Example error

Cloned the repo and tried to run the example folder but got the error below on Line 88

int fib(int n, SendPort port)
package:example/main.dart

The argument type 'int Function(int, SendPort)' can't be assigned to the parameter type 'FutureOr<dynamic> Function(int, TypeSendPort<dynamic>)'.dart[argument_type_not_assignable](https://dart.dev/diagnostics/argument_type_not_assignable)

Fixed by changing SendPort to TypeSendPort

Memory leak?

Hi there,
When I use this package, it shows twice isolates than cores of my CPU. Normally the quantity is 8 and current it is 16. The memory usage is much higher than normal level(~3.5G comparing with ~350M)

image
image

My question is that when I call it as below
final result1 = await Executor().execute(arg1: someRepo, arg2: page, fun2: fetchUsers);
final result2 = await Executor().execute(arg1: someRepo, arg2: page, fun2: fetchUsers);

Asume that the fetchUsers will take very long time, so the Executor() knows that arrange the tasks to different isolates or queue. Right? the opposite is crash.

Thank you.

Undefined name 'WorkPriority'

Hello!

I upgraded to 4.2.3version and get an error now:

Undefined name 'WorkPriority'.
Try correcting the name to one that is defined, or defining the name.

My code:

import 'package:worker_manager/worker_manager.dart';

Executor()
    .execute(fun1: getReleaseNotes, arg1: '', priority: WorkPriority.low)
    .then((value) {
      ...
    });

But I see that parameter in docs of execute method:

Cancelable<O> execute<A, B, C, D, O>({
  A arg1,
  B arg2,
  C arg3,
  D arg4,
  FutureOr<O> Function(A) fun1,
  FutureOr<O> Function(A, B) fun2,
  FutureOr<O> Function(A, B, C) fun3,
  FutureOr<O> Function(A, B, C, D) fun4,
  WorkPriority priority = WorkPriority.high,
  bool fake = false,
})
package:worker_manager/src/scheduling/executor.dart

How I can use priority now?

Undetermined Nullability on flutter web when import worker_manager

import 'package:flutter/material.dart';

import 'package:worker_manager/worker_manager.dart';

void main() {
  runApp(Container());
}
[✓] Flutter (Channel stable, 2.0.4, on Microsoft Windows [Version 10.0.19042.985], locale en-IN)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Android Studio
[√] VS Code, 64-bit edition (version 1.56.2)
[√] Connected device (2 available)
Launching lib\main.dart on Chrome in debug mode...
lib\main.dart:1
Unhandled exception:
Unsupported operation: Undetermined Nullability
#0      ProgramCompiler._emitFutureOrType (package:dev_compiler/src/kernel/compiler.dart:2894:7)
#1      ProgramCompiler._normalizeFutureOr (package:dev_compiler/src/kernel/compiler.dart:2763:12)

#2      ProgramCompiler.visitFutureOrType (package:dev_compiler/src/kernel/compiler.dart:2776:7)
#3      FutureOrType.accept (package:kernel/ast.dart:11126:42)

#4      ProgramCompiler._emitType (package:dev_compiler/src/kernel/compiler.dart:2692:54)
#5      ProgramCompiler._emitArgumentList (package:dev_compiler/src/kernel/compiler.dart:5404:41)
#6      ProgramCompiler._emitMethodCall (package:dev_compiler/src/kernel/compiler.dart:4721:16)

#7      ProgramCompiler.visitInstanceInvocation (package:dev_compiler/src/kernel/compiler.dart:4641:12)
#8      InstanceInvocation.accept (package:kernel/ast.dart:5178:44)
#9      ProgramCompiler._visitExpression (package:dev_compiler/src/kernel/compiler.dart:3705:20)

#10     ProgramCompiler.visitExpressionStatement (package:dev_compiler/src/kernel/compiler.dart:3786:12)
#11     ExpressionStatement.accept (package:kernel/ast.dart:8462:43)

#12     ProgramCompiler._visitStatement (package:dev_compiler/src/kernel/compiler.dart:3611:20)
#13     MappedListIterable.elementAt (dart:_internal/iterable.dart:412:31)

#14     ListIterator.moveNext (dart:_internal/iterable.dart:341:26)
#15     new _GrowableList._ofEfficientLengthIterable (dart:core-patch/growable_array.dart:188:27)
#16     new _GrowableList.of (dart:core-patch/growable_array.dart:150:28)

#17     new List.of (dart:core-patch/array_patch.dart:50:28)
#18     ListIterable.toList (dart:_internal/iterable.dart:212:44)

How can I know if the warmUp method was called or call warmUpr safely more than 1 time?

Hi, i want to use this in my package but I don't want the user call warmUp in the main.

I want to call it only in the class that use it, and i want to do something like this?

If(Executor.canWarmUp){
  Executor().warmUp();
}

But ideally I want to call Executor().warmUp(); as many times i want and the executor do this check internally, to no add more Isolate wrappers to the pool

WarmUp is not warming up

WarminUp seems to not warm up properly or am I missing something?

main() async {
  await Executor().warmUp();
  final lines = await loadFile();

  print("First Try");
  DateTime now = DateTime.now();
  for (final line in lines) {
    Executor().execute(arg1: line, fun1: callback).then((_) => print(
        "Paralel time: ${DateTime.now().difference(now).inMilliseconds}"));
  }

  // Wait enough seconds to make sure first try ended
  Future.delayed(Duration(seconds: 10));
  print("Second try");
  now = DateTime.now();
  for (final line in lines) {
    Executor().execute(arg1: line, fun1: callback).then((_) => print(
        "Paralel time: ${DateTime.now().difference(now).inMilliseconds}"));
  }
}
23 has been spawned
initialized
Load done
added task with number -9007199254740992
isolate with task number -9007199254740992 begins work
added task with number -9007199254740991
isolate with task number -9007199254740991 begins work
added task with number -9007199254740990
isolate with task number -9007199254740990 begins work
added task with number -9007199254740989
isolate with task number -9007199254740989 begins work
added task with number -9007199254740988
isolate with task number -9007199254740988 begins work
added task with number -9007199254740987
isolate with task number -9007199254740987 begins work
added task with number -9007199254740986
isolate with task number -9007199254740986 begins work
added task with number -9007199254740985
isolate with task number -9007199254740985 begins work
added task with number -9007199254740984
isolate with task number -9007199254740984 begins work
added task with number -9007199254740983
isolate with task number -9007199254740983 begins work
added task with number -9007199254740982
isolate with task number -9007199254740982 begins work
isolate with task number -9007199254740985 ends work
Paralel time: 4060
isolate with task number -9007199254740982 ends work
Paralel time: 4069
isolate with task number -9007199254740983 ends work
Paralel time: 4079
isolate with task number -9007199254740986 ends work
Paralel time: 4094
isolate with task number -9007199254740990 ends work
Paralel time: 4097
isolate with task number -9007199254740984 ends work
Paralel time: 4104
isolate with task number -9007199254740992 ends work
Paralel time: 4122
isolate with task number -9007199254740987 ends work
Paralel time: 4146
isolate with task number -9007199254740991 ends work
Paralel time: 4157
isolate with task number -9007199254740989 ends work
Paralel time: 5002
isolate with task number -9007199254740988 ends work
Paralel time: 5170
New test
added task with number -9007199254740981
isolate with task number -9007199254740981 begins work
added task with number -9007199254740980
isolate with task number -9007199254740980 begins work
added task with number -9007199254740979
isolate with task number -9007199254740979 begins work
added task with number -9007199254740978
isolate with task number -9007199254740978 begins work
added task with number -9007199254740977
isolate with task number -9007199254740977 begins work
added task with number -9007199254740976
isolate with task number -9007199254740976 begins work
added task with number -9007199254740975
isolate with task number -9007199254740975 begins work
added task with number -9007199254740974
isolate with task number -9007199254740974 begins work
added task with number -9007199254740973
isolate with task number -9007199254740973 begins work
added task with number -9007199254740972
isolate with task number -9007199254740972 begins work
added task with number -9007199254740971
isolate with task number -9007199254740971 begins work
isolate with task number -9007199254740975 ends work
Paralel time: 20
isolate with task number -9007199254740974 ends work
Paralel time: 25
isolate with task number -9007199254740972 ends work
Paralel time: 34
isolate with task number -9007199254740971 ends work
Paralel time: 35
isolate with task number -9007199254740979 ends work
Paralel time: 36
isolate with task number -9007199254740973 ends work
Paralel time: 74
isolate with task number -9007199254740981 ends work
Paralel time: 93
isolate with task number -9007199254740976 ends work
Paralel time: 124
isolate with task number -9007199254740980 ends work
Paralel time: 143
isolate with task number -9007199254740978 ends work
Paralel time: 1011
isolate with task number -9007199254740977 ends work
Paralel time: 1171

Same exact work.
First try took 5170 ms.
And Second try took 1171 ms.

It seems that the Executor has still to warm up but it's supposed to be up..
Or am I missing something?

targetWorker.kill().then((_) => targetWorker.initialize().then((_) => _scheduleNext())); can not await cause Bad state: Stream has already been listened to.

void _cancel<A, B, C, D, O>(Task<A, B, C, D, O> task) {
if (!task.resultCompleter.isCompleted) {
task.resultCompleter.completeError(CanceledError());
}
if (_queue.contains(task)) {
_logInfo('[timeline] task with number ${task.number} removed from queue');
_queue.remove(task);
} else {
final targetWorker = pool.firstWhereOrNull((iw) => iw.runnableNumber == task.number);
if (targetWorker != null) {
logInfo('[timeline] isolate with number ${targetWorker.runnableNumber} killed');
targetWorker.kill().then((
) => targetWorker.initialize().then((
) => _scheduleNext()));
}
}
}

demo:

int fib(int n) {
if (n < 2) {
return n;
}
return fib(n - 2) + fib(n - 1);
}

Cancelable task;
void perform(){
task?.cancel();
task = Executor().execute(arg1: 41, fun1: fib);
//task can be canceled if you need it, for example in dispose method in widget, block, presenter to stop parsing or
//long calculation
}

void test() {
for(int i = 0;i <=3;i++) {
perform();
}
}

use methodchannel

Unhandled Exception: cant send error with too big stackTrace, error is : Invalid argument(s): Illegal argument in isolate message : (object is a StackTrace)

Cancelable.mergeAll get error Bad State after cancel

hi, i try to uploading image with multiple Executor with Cancelable.mergeAll(), on process uploading, i try to cancel upload, but i get error log like this:

Bad state: Stream has already been listened to.
------- STACK TRACE -------
#0      _StreamController._subscribe (dart:async/stream_controller.dart:676:7)
#1      _ControllerStream._createSubscription (dart:async/stream_controller.dart:827:19)
#2      _StreamImpl.listen (dart:async/stream_impl.dart:473:9)
#3      _ReceivePortImpl.listen (dart:isolate-patch/isolate_patch.dart:91:31)
#4      WorkerImpl.initialize (package:worker_manager/src/worker/worker_io.dart:24:29)
<asynchronous suspension>

it's a bug?, but before, i try upload single file and using Executor().execute() and try to kill isolate when the process upload, everything good.

Isolate task function with no void return type throws an error

When we have an isolate task function with void return type, an error is thrown.

Unhandled Exception: type 'Null' is not a subtype of type 'Object'
#0      _AsyncCompleter.complete (dart:async/future_impl.dart:36:41)
#1      WorkerImpl.initialize.<anonymous closure> (package:worker_manager_v2/src/worker/worker_io.dart:31:17)
#2      _rootRunUnary (dart:async/zone.dart:1442:13)
#3      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#4      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#5      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#6      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#7      _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#8      _StreamController._add (dart:async/stream_controller.dart:648:7)
#9      _StreamController.add (dart:async/stream_controller.dart:596:5)
#10     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)

Version solving failed

I have started a new project and just added the dependency but it got failed at verification can you check where it went wrong


Because every version of flutter_test from sdk depends on async 2.4.0 and worker_manager >=2.4.8 depends on async ^2.4.1, flutter_test from sdk is incompatible with worker_manager >=2.4.8.

So, because taskdemo depends on both worker_manager ^2.5.0 and flutter_test any from sdk, version solving failed.
pub get failed (1; So, because taskdemo depends on both worker_manager ^2.5.0 and flutter_test any from sdk, version solving failed.)

Update CHANGELOG

Please update the CHANGELOG.md to keep the developer up to date.

Task is not invoked when there are more tasks than Isolates

On my machine the Executor spawns 7 isolates and for testing I call 8 tasks to be executed at the same time, and then the Executor only invokes the first 7 tasks leaving the last one out of the execution.
The behavior expected by me would be that as soon as an isolate was released the execution of the last task would be carried out.

Follow the code used for the tests

import 'package:worker_manager/worker_manager.dart';

void main() async {
  await Executor().warmUp(log: true);
  increment('fn1', 1);
  increment('fn2', 2);
  increment('fn3', 3);
  increment('fn4', 4);
  increment('fn5', 5);
  increment('fn6', 6);
  increment('fn7', 7);
  increment('fn8', 8);
}

Future<int> isolateTask(String name, int value) async {
  print('run isolateTask $name');
  await Future.delayed(Duration(seconds: 1));
  return value++;
}

Future<void> increment(String name, int n) async {
  await Executor()
      .execute(arg1: name, arg2: n, fun2: isolateTask)
      .next((value) => print('task $name, value $value'));
}

Cosole output

7 has been spawned
initialized
inserted task with number -9007199254740992
isolate with task number -9007199254740992 begins work
inserted task with number -9007199254740991
isolate with task number -9007199254740991 begins work
inserted task with number -9007199254740990
isolate with task number -9007199254740990 begins work
inserted task with number -9007199254740989
isolate with task number -9007199254740989 begins work
inserted task with number -9007199254740988
isolate with task number -9007199254740988 begins work
inserted task with number -9007199254740987
isolate with task number -9007199254740987 begins work
inserted task with number -9007199254740986
isolate with task number -9007199254740986 begins work
inserted task with number -9007199254740985
run isolateTask fn6
run isolateTask fn3
run isolateTask fn4
run isolateTask fn2
run isolateTask fn1
run isolateTask fn7
run isolateTask fn5
isolate with task number -9007199254740990 ends work
task fn3, value 3
isolate with task number -9007199254740987 ends work
task fn6, value 6
isolate with task number -9007199254740989 ends work
task fn4, value 4
isolate with task number -9007199254740991 ends work
task fn2, value 2
isolate with task number -9007199254740992 ends work
task fn1, value 1
isolate with task number -9007199254740986 ends work
task fn7, value 7
isolate with task number -9007199254740988 ends work
task fn5, value 5

i tested with version 3.0.0 and 2.8.4 of worker_manager

error in example

whenever i run the code, i get this

I/flutter (17353): ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
I/flutter (17353): The following RangeError was thrown while handling a gesture:
I/flutter (17353): RangeError (index): Invalid value: Valid value range is empty: 0
I/flutter (17353):
I/flutter (17353): When the exception was thrown, this was the stack:
I/flutter (17353): #0 List.[] (dart:core-patch/growable_array.dart:147:60)
I/flutter (17353): #1 _RegularScheduler._warmUpFirst (package:worker_manager/scheduler.dart:42:42)
I/flutter (17353): #2 _RegularScheduler.manageQueue (package:worker_manager/scheduler.dart:24:7)
I/flutter (17353): #3 _WorkerManager.addTask (package:worker_manager/executor.dart:54:50)
I/flutter (17353): #4 _PendingUploadsPageState.build. (package:ereader/pages/pending_uploads.dart:98:34)
I/flutter (17353): #5 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:654:14)
I/flutter (17353): #6 _InkResponseState.build. (package:flutter/src/material/ink_well.dart:729:32)
I/flutter (17353): #7 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
I/flutter (17353): #8 TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:365:11)
I/flutter (17353): #9 TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:275:7)
I/flutter (17353): #10 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:455:9)
I/flutter (17353): #11 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:75:13)
I/flutter (17353): #12 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:102:11)
I/flutter (17353): #13 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:218:19)
I/flutter (17353): #14 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22)
I/flutter (17353): #15 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7)
I/flutter (17353): #16 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7)
I/flutter (17353): #17 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7)
I/flutter (17353): #21 _invoke1 (dart:ui/hooks.dart:263:10)
I/flutter (17353): #22 _dispatchPointerDataPacket (dart:ui/hooks.dart:172:5)
I/flutter (17353): (elided 3 frames from package dart:async)
I/flutter (17353):
I/flutter (17353): Handler: "onTap"
I/flutter (17353): Recognizer:
I/flutter (17353): TapGestureRecognizer#5b7f1
I/flutter (17353): ═════════

Endless running

I'm just curious. Could you explain why local function is running endless without any errors?

Flutter doctor:

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, 2.3.0-1.0.pre.144, on Mac OS X 10.15.7 19H2 darwin-x64, locale en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.1)
[✓] Connected device (3 available)

• No issues found!
import 'package:flutter_test/flutter_test.dart';
import 'package:worker_manager/worker_manager.dart';

int fibStatic(int n) {
  print('n: $n');
  if (n < 2) {
    return n;
  }
  return fibStatic(n - 2) + fibStatic(n - 1);
}

Future<void> main() async {
  await Executor().warmUp();

  // endless test
  test('isolate infinite run', () async {
    int fibLocal(int n) {
      print('n: $n');
      if (n < 2) {
        return n;
      }
      return fibLocal(n - 2) + fibLocal(n - 1);
    };

    await Executor()
        .execute<int, void, void, void, int>(arg1: 3, fun1: fibLocal)
        .then((data) {
      print('result $data');
    });
  });

  // success test
  test('isolate success run', () async {
    await Executor()
        .execute<int, void, void, void, int>(arg1: 3, fun1: fibStatic)
        .then((data) {
      print('result $data');
    });
  });
}

Isolate main is already scheduled on mutator thread 0xa8f9f400, failed to schedule from os

I have a listview, I use Executor to run a task to get data in background for continuous scroll listview, the code run ok, but it's random crash on real device, release build with error message from the log:

../../third_party/dart/runtime/vm/dart_api_impl.cc: 1708: error: Isolate main is already scheduled on mutator thread 0xa8f9f400, failed to schedule from os thread 0x5b27

if I remove worker_manager, the app run well without crash, I dont know why the crash occured by chance, not by request data because the app run well without create isolate.

 Flutter (Channel master, 1.25.0-5.0.pre.106, on Mac OS X 10.14.6
    • Flutter version 1.25.0-5.0.pre.106 at /Users/admin/dev/flutter/flutter
    • Framework revision bd68225598 (10 hours ago), 2020-12-07 19:58:04 -0500
    • Engine revision a26e80c931
    • Dart version 2.12.0 (build 2.12.0-125.0.dev)

addition logs:

pthread_create failed: couldn't allocate 528384-bytes mapped space: Out of memory
W/libc    ( 9741): pthread_create failed: couldn't allocate 528384-bytes mapped space: Out of memory

Should we kill the isolate task manually in case of exceptions?

I noticed that whenever the isolate-function throws an error, the isolate task itself isn't terminated and continues to run indefinitely. Is that required behavior? Should we be killing off the task ourselves after exception handling?

import 'package:flutter_test/flutter_test.dart';
import 'package:worker_manager/worker_manager.dart';

// This is to demonstrate that the isolate is not terminated after an exception
Future<void> _isolateTask(String? name) async {
  await Future.delayed(const Duration(milliseconds: 1000));
  return Future.error("MyCustomException");
}

void main() {
  test('', () async {
    await Executor().warmUp(log: true);
    try {
      await Executor().execute(arg1: 'test', fun1: _isolateTask);
    } catch (e) {
      print('Caught error: $e');
    }
    await Future.delayed(const Duration(seconds: 15));
  });
}

Output

3 has been spawned
initialized
added task with number -9007199254740992
isolate with task number -9007199254740992 begins work
Caught error: MyCustomException

I am running this on Linux (Fedora 35), Flutter 2.5.3 stable. Noticed this after seeing my new isolate task waiting to start after getting exceptions from running tasks.

Second run won't start

Hi, I haven't found a solution in your docs nor in previously closed tickets, so will write a new one hoping it's just me.

So I'm trying to use the library in Flutter web, and everything works super great, but only the first time.
What is clear from the logs is that the second time I call the Executor().execute(); for the same thing, never starts working.

Basically what I am trying to achieve is doing an API call with dart:http, and parsing the response from JSON to a List of objects mapped to that JSON.

This would be method that is getting called from the Executor:

  Future<MyObject> mapJsonToEnrolment(String url) async {
    var result = await http.get(Uri.parse(url));
    var response = MyResponse();
    response.statusCode = result.statusCode;
    response.myObject = jsonDecode(result.body)
        .map<MyObject>((json) => MyObject.fromJson(json))
        .toList();
    return response;
  }

And this is how it's getting called:

Future<List<MyObject>> getMyObjectForPage(
    String page, {
  }) async {
    try {
      var url = "https://.......";
      final myResponse = await Executor().execute(arg1: url, fun1: mapJsonToEnrolment);

      if (myResponse.statusCode == 200) {
        return myResponse.myObject;
      } else {
        throw MyException(type: MyExceptionType.UNKNOWN);
      }
    } on Exception catch (_) {
      throw MyException(type: MyExceptionType.UNKNOWN);
    }
  }

The first time I call getMyObjectForPage() works just fine, but the second time it never starts the Task.

Is it just me doing something wrong or? Thanks for the library btw! :)

decodeImage with worker in flutter web

Hello, I tried this library to decode an Image in flutter web but the UI still freeze

Im.Image image = await Executor().execute(arg1: file, fun1: Im.decodeImage);

Do you know why?

Error with flutter pub get at Stable flutter channel

Because every version of flutter_test from sdk depends on async 2.6.1 and worker_manager >=4.2.0 depends on async ^2.8.1, flutter_test from sdk is incompatible with worker_manager >=4.2.0.```

flutter doctor output:
```[✓] Flutter (Channel stable, 2.2.3, on Mac OS X
    10.15.7 19H15 darwin-x64, locale ru-RU)
    • Flutter version 2.2.3 at
      /Users/idrats/Documents/flutter
    • Framework revision f4abaa0735 (5 weeks
      ago), 2021-07-01 12:46:11 -0700
    • Engine revision 241c87ad80
    • Dart version 2.13.4

[✓] Android toolchain - develop for Android
    devices (Android SDK version 30.0.2)
    • Android SDK at
      /Users/idrats/Library/Android/sdk
    • Platform android-30, build-tools 30.0.2
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/
      bin/java
    • Java version OpenJDK Runtime Environment
      (build 1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at
      /Applications/Xcode.app/Contents/Developer
    • Xcode 12.4, Build version 12D4e
    • CocoaPods version 1.10.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google
      Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.1)
    • Android Studio at /Applications/Android
      Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨
      https://plugins.jetbrains.com/plugin/9212-
      flutter
    • Dart plugin can be installed from:
      🔨
      https://plugins.jetbrains.com/plugin/6351-
      dart
    • Java version OpenJDK Runtime Environment
      (build 1.8.0_242-release-1644-b3-6222593)

[✓] Connected device (2 available)
    • iPhone 12 mini (mobile) •
      E36EFFD9-7ED0-45B7-8FF7-D83277302351 • ios
      •
      com.apple.CoreSimulator.SimRuntime.iOS-14-
      4 (simulator)
    • Chrome (web)            • chrome
      • web-javascript • Google Chrome
      92.0.4515.107

• No issues found!```

Exception in flutter web - LateInitializationError: Field sendPort has not been initialized

Running the example app throws exceptions in flutter web. And, it looks like tasks get queued up, never executed.

Peek.2022-07-21.19-39.mp4
Error: LateInitializationError: Field 'sendPort' has not been initialized.
    at Object.throw_ [as throw] (http://localhost:40607/dart_sdk.js:5080:11)
    at get sendPort [as sendPort] (http://localhost:40607/packages/worker_manager/src/worker/worker_web.dart.lib.js:309:39)
    at Runnable.new.call (http://localhost:40607/packages/worker_manager/src/worker/worker_web.dart.lib.js:338:34)
    at WorkerImpl._execute (http://localhost:40607/packages/worker_manager/src/worker/worker_web.dart.lib.js:148:23)
    at worker_web.WorkerImpl.new.work (http://localhost:40607/packages/worker_manager/src/worker/worker_web.dart.lib.js:142:71)
    at work.next (<anonymous>)
    at runBody (http://localhost:40607/dart_sdk.js:40660:34)
    at Object._async [as async] (http://localhost:40607/dart_sdk.js:40691:7)
    at worker_web.WorkerImpl.new.work (http://localhost:40607/packages/worker_manager/src/worker/worker_web.dart.lib.js:136:20)
    at [_schedule] (http://localhost:40607/packages/worker_manager/src/worker/worker_web.dart.lib.js:915:28)
    at executing (http://localhost:40607/packages/worker_manager/src/worker/worker_web.dart.lib.js:884:26)
    at worker_manager._Executor._internal.execute (http://localhost:40607/packages/worker_manager/src/worker/worker_web.dart.lib.js:898:16)
    at http://localhost:40607/packages/example/main.dart.lib.js:508:55
    at main._MyHomePageState.new.setState (http://localhost:40607/packages/flutter/src/widgets/title.dart.lib.js:11584:22)
    at http://localhost:40607/packages/example/main.dart.lib.js:506:28
    at tap.TapGestureRecognizer.new.invokeCallback (http://localhost:40607/packages/flutter/src/gestures/recognizer.dart.lib.js:198:18)
    at tap.TapGestureRecognizer.new.handleTapUp (http://localhost:40607/packages/flutter/src/gestures/tap.dart.lib.js:411:42)
    at [_checkUp] (http://localhost:40607/packages/flutter/src/gestures/tap.dart.lib.js:217:12)
    at tap.TapGestureRecognizer.new.handlePrimaryPointer (http://localhost:40607/packages/flutter/src/gestures/tap.dart.lib.js:166:23)
    at tap.TapGestureRecognizer.new.handleEvent (http://localhost:40607/packages/flutter/src/gestures/recognizer.dart.lib.js:444:16)
    at [_dispatch] (http://localhost:40607/packages/flutter/src/gestures/pointer_router.dart.lib.js:86:9)
    at http://localhost:40607/packages/flutter/src/gestures/pointer_router.dart.lib.js:112:26
    at LinkedMap.new.forEach (http://localhost:40607/dart_sdk.js:27745:11)
    at [_dispatchEventToRoutes] (http://localhost:40607/packages/flutter/src/gestures/pointer_router.dart.lib.js:110:29)
    at pointer_router.PointerRouter.new.route (http://localhost:40607/packages/flutter/src/gestures/pointer_router.dart.lib.js:105:37)
    at binding$5.WidgetsFlutterBinding.new.handleEvent (http://localhost:40607/packages/flutter/src/gestures/binding.dart.lib.js:367:26)
    at binding$5.WidgetsFlutterBinding.new.dispatchEvent (http://localhost:40607/packages/flutter/src/gestures/binding.dart.lib.js:355:24)
    at binding$5.WidgetsFlutterBinding.new.dispatchEvent (http://localhost:40607/packages/flutter/src/rendering/layer.dart.lib.js:5440:13)
    at [_handlePointerEventImmediately] (http://localhost:40607/packages/flutter/src/gestures/binding.dart.lib.js:331:14)
    at binding$5.WidgetsFlutterBinding.new.handlePointerEvent (http://localhost:40607/packages/flutter/src/gestures/binding.dart.lib.js:305:43)
    at [_flushPointerEventQueue] (http://localhost:40607/packages/flutter/src/gestures/binding.dart.lib.js:295:14)
    at [_handlePointerDataPacket] (http://localhost:40607/packages/flutter/src/gestures/binding.dart.lib.js:286:54)
    at Object.invoke1 (http://localhost:40607/dart_sdk.js:191747:7)
    at _engine.EnginePlatformDispatcher.__.invokeOnPointerDataPacket (http://localhost:40607/dart_sdk.js:171943:15)
    at [_onPointerData] (http://localhost:40607/dart_sdk.js:172879:49)
    at http://localhost:40607/dart_sdk.js:173317:28
    at http://localhost:40607/dart_sdk.js:173273:16
    at loggedHandler (http://localhost:40607/dart_sdk.js:172978:11)

Can we encode using flutter_ffmpeg inside an Executor?

Encoding with flutter_ffmpeg takes too much time and resources and generates Jank in the UI. So it would be very nice if we could run it in a background thread. Can we do it with the help of your library? If yes, is there a way to get progress callbacks from the thread? I want to show the user how much encoding is done. Normally flutter_ffmpeg gives this callback in its API.

Also, is there a straightforward way to allow this worker to keep on working while the app is in the background?

SendPort has not been initialized

Using latest version 4.2.6

warmUp is not called explicitly.
Doesn't happen always, so it might be some race condition.

LateError: LateInitializationError: Field '_sendPort@3683091195' has not been initialized.
  File "worker_io.dart", in WorkerImpl._sendPort
  File "worker_io.dart", line 46, col 5, in WorkerImpl.work
  File "executor.dart", line 144, col 22, in _Executor._schedule
  File "executor.dart", line 113, col 9, in _Executor.execute.executing
  File "executor.dart", line 122, col 12, in _Executor.execute

Kill isolate pool

There doesn't seem to be a way to dispose of the Executor. Use case is I have a command line app, and the process just hangs when all of the processing is done since the isolates are still alive. I would like the app to exit at that point, so I need a way of killing the isolates. I see there is a kill method on isolate, but the executor pool is private.

Cannot Invoke Platform Calls

I am trying to invoke some platform specific but cannot because of limitations imposed by the platform
could you help me by creating a workaround

[Bug] cold start is not safe on non-web

Reproduce

For example, without warmup, directly start 10 tasks, any task except the first one may raise
LateInitializationError: Field '_sendPort@409091195' has not been initialized.

  for (int i = 0; i < 10; i++) {
    Executor().execute(func1: jsonDecode, arg1: "{}");
  }

Only on non-web, because web is not truly support isolates.

Error log
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: LateInitializationError: Field '_sendPort@409091195' has not been initialized.
#0      WorkerImpl._sendPort (package:worker_manager/src/worker/worker_io.dart)
#1      WorkerImpl.work (package:worker_manager/src/worker/worker_io.dart:43:5)
#2      _Executor._schedule (package:worker_manager/src/scheduling/executor.dart:146:22)
#3      _Executor.execute.executing (package:worker_manager/src/scheduling/executor.dart:115:9)
#4      _Executor.execute (package:worker_manager/src/scheduling/executor.dart:124:12)
#5      testFunction (package:chaldea/_test_page.dart:18:16)
#6      __DebugMenuDialogState.build.<anonymous closure> (package:chaldea/app/modules/root/global_fab.dart:135:24)
#7      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:989:21)
#8      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:198:24)
#9      TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:608:11)
#10     BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:296:5)
#11     BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:230:7)
#12     PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:563:9)
#13     PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:94:12)
#14     PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:139:9)
#15     _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:539:8)
#16     PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:137:18)
#17     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:123:7)
#18     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:439:19)
#19     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:419:22)
#20     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:322:11)
#21     GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:374:7)
#22     GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:338:5)
#23     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:296:7)
#24     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:279:7)
#25     _rootRunUnary (dart:async/zone.dart:1442:13)
#26     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#27     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#28     _invoke1 (dart:ui/hooks.dart:170:10)
#29     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:331:7)
#30     _dispatchPointerDataPacket (dart:ui/hooks.dart:94:31)

Reason

All Worker fields are late.
https://github.com/Renesanse/worker_manager/blob/8d8b525b75f4ad1334526b35897b32b3e600f129/lib/src/worker/worker_io.dart#L8-L12

And the code uses _pool.isEmpty to decide initiated or not. But once WorkerImpl.initialize called, _pool will immediately be inserted a Worker and it's not empty now. However, the actual initiation is not finished.
https://github.com/Renesanse/worker_manager/blob/8d8b525b75f4ad1334526b35897b32b3e600f129/lib/src/worker/worker_io.dart#L22-L35

Enhancement

Use a Completer inside warmUp, and always call warmUp before execute.

// /lib/src/scheduling/executor.dart
class _Executor implements Executor {
  Completer? _completer;

  @override
  Future<void> warmUp({
    bool log = false,
    int? isolatesCount,
  }) async {
    _log = log;
    if (_completer != null) {
      return _completer!.future;
    }
    if (_pool.isEmpty) {
      _completer = Completer();
      Future<void>.microtask(() async {
        final processors = numberOfProcessors;
        isolatesCount ??= processors;
        var processorsNumber =
            isolatesCount! < processors ? isolatesCount : processors;
        if (processorsNumber == 1) processorsNumber = 2;
        for (var i = 0; i < processorsNumber! - 1; i++) {
          _pool.add(Worker());
        }
        _logInfo('${_pool.length} has been spawned');
        await Future.wait(_pool.map((iw) => iw.initialize()));
        _logInfo('initialized');
        _completer!.complete();
        _completer = null;
      }).catchError(_completer!.completeError);
      return _completer!.future;
    } else {
      _logInfo('all workers already initialized');
    }
  }

  @override
  Cancelable<O> execute<A, B, C, D, O>({
    A? arg1,
    B? arg2,
    C? arg3,
    D? arg4,
    Fun1<A, O>? fun1,
    Fun2<A, B, O>? fun2,
    Fun3<A, B, C, O>? fun3,
    Fun4<A, B, C, D, O>? fun4,
    WorkPriority priority = WorkPriority.high,
    bool fake = false,
  }) {
    Cancelable<O> executing(){} // not changed

    return Cancelable.fromFuture(warmUp(log: _log))
        .next(onValue: (_) => executing());
  }
  // other codes not modified
}

Potential bugs

Not investigate into dispose, a Lock maybe better, but even there is a potential bug, it should be prevented by developer so it should not matter.

It doesn't work after 4.0 update

How I should use it now? It just throws argument type error: The argument type 'int Function(int)' can't be assigned to the parameter type 'FutureOr Function(int, TypeSendPort)'.dartargument_type_not_assignable

int fib(int n) {
 if (n < 2) {
  return n;
 }
 return fib(n - 2) + fib(n - 1);
}

void performAction() {
    Executor().execute(arg1: 41, fun1: fib); // The argument type 'int Function(int)' can't be assigned to the parameter type 'FutureOr<dynamic> Function(int, TypeSendPort<dynamic>)'.dart[argument_type_not_assignable](https://dart.dev/diagnostics/argument_type_not_assignable)
}

Compilation error with null safety

Upgrading my project using worker_manager from 4.0.0 to 4.0.1 leads to this compilation error:

../../../.pub-cache/hosted/pub.dartlang.org/worker_manager-4.0.1/lib/src/task.dart:12:27: Error: The parameter 'runnable' can't have a value of 'null' because of its type 'Runnable<A, B, C, D, O>', but the implicit default value is 'null'.
 - 'Runnable' is from 'package:worker_manager/src/runnable.dart' ('../../../.pub-cache/hosted/pub.dartlang.org/worker_manager-4.0.1/lib/src/runnable.dart').
Try adding either an explicit non-'null' default value or the 'required' modifier.
  Task(this.number, {this.runnable, this.workPriority});
                          ^^^^^^^^
../../../.pub-cache/hosted/pub.dartlang.org/worker_manager-4.0.1/lib/src/task.dart:12:42: Error: The parameter 'workPriority' can't have a value of 'null' because of its type 'WorkPriority', but the implicit default value is 'null'.
 - 'WorkPriority' is from 'package:worker_manager/src/work_priority.dart' ('../../../.pub-cache/hosted/pub.dartlang.org/worker_manager-4.0.1/lib/src/work_priority.dart').
Try adding either an explicit non-'null' default value or the 'required' modifier.
  Task(this.number, {this.runnable, this.workPriority});
                                         ^^^^^^^^^^^^
../../../.pub-cache/hosted/pub.dartlang.org/worker_manager-4.0.1/lib/src/executor.dart:81:23: Error: The argument type 'num' can't be assigned to the parameter type 'int'.
    final task = Task(_taskNumber,
                      ^
../../../.pub-cache/hosted/pub.dartlang.org/worker_manager-4.0.1/lib/src/executor.dart:156:7: Error: The argument type 'num' can't be assigned to the parameter type 'int'.
      _taskNumber,
      ^

I don't even have to use the plugin - these errors trigger as soon as I import package:worker_manager/worker_manager.dart in a file migrated to null-safe dart.

Unhandled Exception: NoSuchMethodError: The method '<' was called on null

3.2.7 version in pub.dev is broken and not consistent with master

I'm trying to run an application but receive an exception:

E/flutter ( 9315): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method '<' was called on null.
E/flutter ( 9315): Receiver: null
E/flutter ( 9315): Tried calling: <(8)
E/flutter ( 9315): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
E/flutter ( 9315): #1      _Executor.warmUp (package:worker_manager/src/executor.dart:60:23)
E/flutter ( 9315): #2      main (package:tc_x/main.dart:12:20)
E/flutter ( 9315): #3      _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:231:25)
E/flutter ( 9315): #4      _rootRun (dart:async/zone.dart:1190:13)
E/flutter ( 9315): #5      _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter ( 9315): #6      _runZoned (dart:async/zone.dart:1630:10)
E/flutter ( 9315): #7      runZonedGuarded (dart:async/zone.dart:1618:12)
E/flutter ( 9315): #8      _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:223:5)
E/flutter ( 9315): #9      _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
E/flutter ( 9315): #10     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
E/flutter ( 9315): 

3.2.7 sources:

55  @override
56  Future<void> warmUp({bool log = false, int isolatesCount}) async {
57    _log = log;
58    final processors = numberOfProcessors;
59    var processorsNumber =
60        isolatesCount < processors ? isolatesCount : processors;
61    if (processorsNumber == 1) processorsNumber = 2;
62    for (var i = 0; i < processorsNumber - 1; i++) {
63      _pool.add(IsolateWrapper());
64    }
65    logInfo('${_pool.length} has been spawned');
66    await Future.wait(_pool.map((iw) => iw.initialize()));
67    logInfo('initialized');
68  }

As you can see in line 60 you are trying to compare nullable isolatesCount with processors. But isolatesCount is null and null doesn't have < operator.

I wanted to resolve this issue by myself, but I found that sources in pub.dev and master are not consistent

Close isolate pool

Almost the same as the #40 issue

Imagine a dart cli program with:

main() async {
  await Executor().warmUp();
  final lines = await loadFile();
  for (final line in lines) {
    Executor().execute(arg1: line, fun1: callback).then(print);
  }
}

If i don't call dispose the program will never end.
If i call dispose the program will end before any print.

There doesn't seem to be a way to close the isolate pool.
(Wait for the queue to be empty before killing the pool)

End works immediately

When I try to execute some task in executor, it starts the work and then ends the works immediately. I am hitting some API in the function and the task does not complete.
This is the log.
added task with number -9007199254740992
isolate with task number -9007199254740992 begins work
calllll---->
request type----->lms_content_video
isolate with task number -9007199254740992 ends work

Cancelable<void> lastKnownOperation = await Executor().execute(arg1: UploadRequest(
        fileName: fileName,
        bytes: fileData.file.bytes,
        user: userStream.value,
        type: type == AppConstants.LMS_CONTENT_FILE_DOC_TYPE
            ? 'lms_content_downloadable'
            : type == AppConstants.LMS_CONTENT_FILE_VIDEO_TYPE
            ? 'lms_content_video'
            : 'lms_content_audio'), fun1: uploadVideoFile).next(

    );

    lastKnownOperation.cancel();

Can anyone help me out.
Thanks!🙂

Use Heap as the priority queue data structure

I see currently the priority queue is implemented in a List but working as a Queue, such that the it picks elements from the front and the position of a Task corresponds to its priority. I suggest changing to a Heap because it handles the priorities by itself, you just adds something to it and by the time you ask it to get a Task it gives you the one who "deservers" most (sorry, it was the only term I could think of). Currently there is the high, regular and low priorities, but there is no middle term like ultra-low or regular-low-ish. Heap handles it such that you pass priority by value (1, 2, 3...) and so allows more customization.

Types declaration with api 2.3.0 when implicit_cast is disabled

Hello!
We tried to move to 2.3.0 and realised that we need to declare dummy type parameters on Runnable and on Task:

  Task<String, String, String, String, String, Uint8List> task;

  @override
  void initState() {
    super.initState();
    SchedulerBinding.instance.addPostFrameCallback((_) async {
      File downloadedFile;
      task = Task<String, String, String, String, String, Uint8List>(
          runnable: Runnable<String, String, String, String, String, Uint8List>(
              arg1: widget.url, fun1: downloadFile));
      Executor().addTask<Uint8List>(task: task).listen((bytes) async {

That's because we have implicit_cast disabled in our project. The previous api works fine and has no such drawback so we'll stick with it.

Thanks for your efforts anyway!

can not support platform MethodChannel function ?

for example:
static Future test() async {
await _channel.invokeMethod('test');
}

static void test2(int arg){
test();

}

Executor().execute(arg1: 0, fun1: test2);

report error,log is here:

Binding has not yet been initialized.
The "instance" getter on the ServicesBinding binding mixin is only available once that binding has been initialized.
Typically, this is done by calling "WidgetsFlutterBinding.ensureInitialized()" or "runApp()" (the latter calls the former). Typically this call is done in the "void main()" method. The "ensureInitialized" method is idempotent; calling it multiple times is not harmful. After calling that method, the "instance" getter will return the binding.
In a test, one can call "TestWidgetsFlutterBinding.ensureInitialized()" as the first line in the test's "main()" method to initialize the binding.
If ServicesBinding is a custom binding mixin, there must also be a custom binding class, like WidgetsFlutterBinding, but that mixes in the selected binding, and that is the class that must be constructed before using the "instance" getter.

why throw a Type when timeout

I think throw TimeoutException("worker execute timeout", task.timeout) is better than throw a type TimeoutException

Can't use worker_manager >=4.0.3 on flutter 2.2 in beta or stable channel

Because every version of flutter_test from sdk depends on async 2.6.1 and worker_manager >=4.0.3 depends on async ^2.7.0, flutter_test from sdk is incompatible with worker_manager >=4.0.3.
[✓] Flutter (Channel beta, 2.2.0, on Microsoft Windows [Version 10.0.19042.985], locale en-IN)
[✓] Flutter (Channel stable, 2.2.1, on Microsoft Windows [Version 10.0.19042.985], locale en-IN)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Android Studio
[√] VS Code, 64-bit edition (version 1.56.2)
[√] Connected device (2 available)

Example app doesn't run in Chrome

The app in the example folder is not made for flutter web. It doesn't run in Chrome. Throws an unimplemented error.

======== Exception caught by scheduler library =====================================================
The following UnimplementedError was thrown during a scheduler callback:
UnimplementedError

When the exception was thrown, this was the stack: 
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 251:49  throw_
lib/_engine/engine/canvaskit/layer_scene_builder.dart 35:5                    addPerformanceOverlay
packages/flutter/src/rendering/layer.dart 901:12                              addToScene
packages/flutter/src/rendering/layer.dart 546:5                               [_addToSceneWithRetainedRendering]
packages/flutter/src/rendering/layer.dart 1106:12                             addChildrenToScene
packages/flutter/src/rendering/layer.dart 1681:5                              addToScene
packages/flutter/src/rendering/layer.dart 938:5                               buildScene
packages/flutter/src/rendering/view.dart 228:30                               compositeFrame
packages/flutter/src/rendering/binding.dart 508:18                            drawFrame
packages/flutter/src/widgets/binding.dart 892:13                              drawFrame
packages/flutter/src/rendering/binding.dart 370:5                             [_handlePersistentFrameCallback]
packages/flutter/src/scheduler/binding.dart 1146:15                           [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1083:9                            handleDrawFrame
packages/flutter/src/scheduler/binding.dart 864:7                             <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:19       internalCallback
====================================================================================================

Does not work in Safari

For some reason this package does not work in safari, but works on chromium based browsers. 🙁

Hosted here for preview

Screen.Recording.2021-03-15.at.7.32.17.PM.mov
Future<void> _loadData() async {
    state = const AsyncValue.loading();
    state = await AsyncValue.guard(
        () async => rootBundle.load('assets/channels.zip').then(
              (value) async => Executor().execute(
                  fun1: iptvOrgFromJson,
                  arg1: value,
                  priority: WorkPriority.immediately),
              onError: (err) => AsyncValue.error(err),
            ));
  }

///

List<IptvOrg> iptvOrgFromJson(ByteData value) => List<IptvOrg>.from(json
    .decode(String.fromCharCodes(ZipDecoder()
        .decodeBytes(
          value.buffer.asUint8List(),
        )
        .files
        .first
        .content as Iterable<int>))
    .map((x) => IptvOrg.fromJson(x)));
[✓] Flutter (Channel master, 2.1.0-13.0.pre.103, on macOS 11.3 20E5196f darwin-x64, locale en-US)
    • Flutter version 2.1.0-13.0.pre.103 at /Users/mahesh/Sdk/flutter
    • Framework revision 0cbe597540 (4 hours ago), 2021-03-15 16:28:02 -0700
    • Engine revision 20375cebcf
    • Dart version 2.13.0 (build 2.13.0-137.0.dev)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Users/mahesh/Library/Android/sdk
    • Platform android-30, build-tools 30.0.3
    • Java binary at: /Applications/Android Studio 4.2 Preview.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.4, Build version 12D4e
    • CocoaPods version 1.10.0

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio
    • Android Studio at /Applications/Android Studio 4.2 Preview.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-x64     • macOS 11.3 20E5196f darwin-x64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 89.0.4389.82

• No issues found!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.