Task Runner: run async tasks with bounded concurrency and receive results as they finish.
This package provides a simple TaskRunner<T> that executes Task<T> in parallel (up to concurrency) and emits TaskResult<T> on a stream as each task completes. Errors are surfaced via stream.addError without stopping other tasks.
Add to your pubspec.yaml:
dependencies:
task_runner: ^0.0.1import 'dart:async';
import 'package:task_runner/task_runner.dart';
Future<void> main() async {
// Prepare tasks (any async work returning T)
final tasks = List.generate(5, (i) => Task<int>(
id: 'task-$i',
run: () async {
await Future.delayed(Duration(milliseconds: 200 + i * 50));
return i * i; // some async computation
},
));
// Create a runner with desired parallelism
final runner = TaskRunner<int>(concurrency: 2, initialTasks: tasks);
// Listen to results as they arrive
final sub = runner.stream.listen(
(TaskResult<int> result) {
print('Done: ${result.id} => ${result.data}');
},
onError: (e, st) => print('Task error: $e'),
onDone: () => print('All tasks finished.'),
);
await sub.asFuture();
}-
class Task<T>- id: unique identifier you assign for the task
- run:
Future<T> Function()to execute
-
class TaskResult<T>- id: the originating task id
- data: the resolved value of type
T
-
class TaskRunner<T>TaskRunner({required int concurrency, List<Task<T>>? initialTasks, bool? stayAlive, void Function()? onFinish})void add(Task<T> task)void addAll(Iterable<Task<T>> tasks)void stop()Stream<TaskResult<T>> get streamint get queueLengthint get runnerCountbool get isStopped
- Runs up to
concurrencytasks simultaneously. - Emits each
TaskResult<T>as soon as its task finishes. - If a task throws, the error is emitted via
stream.addErrorand other tasks continue. - When the queue drains and there are no active runners, the stream completes. If
stayAliveistrue, the stream stays open untilstop()is called.
See the runnable console sample in /example. Run it with:
dart run example/main.dart