A simple package for working with multithreading, using an interface similar to Task in C#.

Overview

Languages:

English Russian

Introduction

Earlier, in order to simplify interactions with isolates in Dart, I started developing actor framework - Theater.

However, not everyone can like both the actor model itself, which is implemented by isolates in Dart, and the actor framework.

In addition to Dart, I also write in C# and, as for me, it has a convenient wrapper for working with multithreading - Task.

I decided to do something in Dart as similar as possible to Task in C#, but with some nuances due to the fact that isolates are still used under the hood.

About Ossa

Provides a convenient wrapper for working with isolates similar to Task in C#.

Installing

Add Ossa to your pubspec.yaml file:

dependencies:
  ossa: ^1.0.2

Import ossa in file that it will be used:

import 'package:ossa/ossa.dart';

What is Task

Each task is started and runs in a separate isolate, tasks can return some result.

As already mentioned in the introduction, I tried to make the tasks as similar as possible to the Task in C#. However, there are differences.

For example, instead of a pool of isolates (in C#, a pool of threads) to which tasks are redirected and then executed, in Ossa, each task you create has its own isolate.

Each task manages the lifecycle of its isolate.

Task types

There are two types of tasks:

  • one shot (default);
  • reusable.

The difference between these two types is that one shot tasks, after completing the task (including if the execution failed), call their dispose method, destroy their isolate and close all StreamController-s used by them, that is, releases all resources used by it. Reusable tasks do not do this, it is calculated that after creating a task you will use it repeatedly.

Why use a reused task instead of creating a new task in the future, if necessary? - so as not to create a new isolate every time.

Task run

There are two ways to start a task:

  • using the run method;
  • creating task, initializing it and running it yourself.

Example of create and start task using the run method:

void main() async {
  // Create and run Task using run method
  var task = await Task.run((context) {
    print('Hello, from task!');
  });

  // Wait when task is completed
  await task.result();
}

Example of create task, initializing it and starting:

void main() async {
  // Create task
  var task = Task((context) {
    print('Hello, from task!');
  });

  // Initialize task before work with him
  await task.initialize();

  // Start task
  await task.start();

  // Wait when task is completed
  await task.result();
}

Get result

The task can return the result of execution. When creating a task yourself, or creating and running using the run method, you can specify a Generic type that should return a Task.

You can process the result both asynchronously using the onDone handler, and wait for the result to be received using the Future received when calling the result method.

The result method, when the task is running, will wait for the result from the isolate, and then return it. If the task has already been completed at the time of calling the result method and has not been started again, it will return the result from the previous task run.

Getting the result from the Future received when calling the result method:

void main() async {
  // Create and run Task with double return type using run method
  var task = await Task.run<double>((context) => 3 * 7);

  // Wait result from Task
  var result = await task.result();

  print(result);
}

Expacted output:

21

Asynchronous receipt of the result using the onDone handler:

void main() async {
  // Create and run task with int return type, set onDone handler
  var task = await Task.run<int>((context) {
    return 5 * 10;
  }, onDone: (value) async {
    print(value);
  });
}

Expected output:

50

Passing data to task

Each task is executed in its own isolate. Isolates do not have shared memory with each other. Therefore, the data that the task should work with is passed to it using the data parameter in the run and start methods.

Example of transferring data to a task:

void main() async {
  // We have some data
  var number = 100;

  // Create and run task using run method, passing data to task
  var task = await Task.run<int>((context) {
    var number = context.get<int>('number');

    return number * 10;
  }, data: {'number': number});

  // Wait when task is completed
  var result = await task.result();

  print(result);
}

Expected output:

1000

Task status

A task has different statuses during its life cycle:

  • not initialized (notInitialized);
  • waiting to start (waitingToRun);
  • running (running);
  • paused (paused);
  • disposed (disposed).

The task is not initialized when created without using the run method, before executing the initialize method. At this point, the task isolate has not yet been created and requires initialization before the task can be executed.

After starting the initialize method, the task is waiting to be started. It is ready to be executed and is waiting for the start method to be executed.

The task is in the execution status after the start method is executed, it can be paused (the task isolate is paused).

If the task is paused, then its execution can be resumed.

After disposed the task, its isolate is destroyed, all Stream Controllers are closed. Further use of this task instance is not possible.

Error handling

An exception may occur during the execution of the task.

There are options for processing it:

  • processing using the onError handler;
  • conclusion of a part of the code with the expectation of a result in try/catch.

Example of handling an exception using the onError handler, asynchronously processing the result of the task execution:

void main() async {
  late Task task;

  // Create and run Task using run method, set onError handler
  task = await Task.run<void>((context) {
    throw FormatException();
  }, onError: (error) async {
    print(error.object.toString());

    task.dispose();
  });
}

If the onError handler was not set at the start of the task, then there are 2 scenarios what will happen to it:

  • if you are waiting for the result of the task asynchronously, that is, using the onDone handler, then nothing will happen, the exception will not be handled in any way. The task will change from the running status to the ready for execution status (waitingToRun);
  • if you are waiting for the result of the task using the result method, the exception will be called again called already in the result method.

Example of handling an exception without onError handler, waiting for the result using the result method:

void main() async {
  // Create and run Task using run method
  var task = await Task.run((context) {
    throw FormatException();
  });

  try {
    // Wait when task is completed
    await task.result();
  } catch (object) {
    // Handle error

    if (object is TaskCompleteException) {
      print(object);

      await task.dispose();
    }
  }
}
You might also like...

Find The Latest trending and upcoming movies and tv shows with MovieDB app. The app contains all info about movies and tv shows. find similar movies or shows, Browse all genres, video trailers, backdrops, logos, and posters.

MovieDB App Features. Dynamic Theming Search Functionality Onboarding-Screen Select favourite movie Home Screen Tranding movie Movies different catego

Dec 12, 2022

A Gherkin parsers and runner for Dart and Flutter which is very similar to cucumber

flutter_gherkin A fully featured Gherkin parser and test runner. Works with Flutter and Dart 2. This implementation of the Gherkin tries to follow as

Nov 18, 2022

(RPG maker) Create RPG-style or similar games more simply with Flame.

(RPG maker) Create RPG-style or similar games more simply with Flame.

Bonfire Build RPG games and similar with the power of FlameEngine! Bonfire is ideal for building games from the following perspectives: Test our onlin

Jan 7, 2023

A Flutter widget to show an icon collection to pick. This widget extend TextField and has a similar behavior as TextFormField

A Flutter widget to show an icon collection to pick. This widget extend TextField and has a similar behavior as TextFormField

icon_picker A Flutter widget to show an icon collection to pick. This widget extend TextField and has a similar behavior as TextFormField Usage In the

Sep 27, 2022

Apply values per media breakpoints. Breakpoints are similar to the breakpoints used in bootstrap css framework.

Apply values per media breakpoints. Breakpoints are similar to the breakpoints used in bootstrap css framework.

Apply values per media breakpoints. Breakpoints are similar to the breakpoints used in bootstrap css framework.

Mar 26, 2021

TheMathU Similarity Index App will accept a mathematical problem as user input and return a list of similar problems that have memorandums.

TheMathU Similarity Index App will accept a mathematical problem as user input and return a list of similar problems that have memorandums.

Technologies MathU Similarity Index - Segmentation Cult The MathU Similarity Index App accepts a mathematical problem as user input and returns a list

Nov 2, 2022

A platform similar to iFood that makes it easier for the consumers to find a list of generators with solar plates system available for rent

iEnergy App A platform similar to iFood that makes it easier for the consumers to find a list of generators with solar plates system available for ren

Jun 7, 2022

Flutter package for displaying grid view of daily task like Github-Contributions.

Flutter package for displaying grid view of daily task like Github-Contributions.

flutter_annual_task flutter_annual_task Flutter package for displaying grid view of daily task like Github-Contributions. Example Usage Make sure to c

Sep 21, 2022
Comments
  • How to use async method inside a task?

    How to use async method inside a task?

    I have plugin methods I would like to start in a separated isolate and wanted to use ossa for this since the API is way better than standard isolate one. However the following code does not seems to work:

    void main() async {
      // Create and run Task using run method
      var task = await Task.run((context) async {
        await futureMethod();
      });
    
      // Wait when task is completed
      await task.result();
    }
    

    Is there any way to bypass this?

    opened by FredJul 5
Owner
Gleb Batykov
21-year-old student. I write mainly in Dart/Flutter and C#
Gleb Batykov
Daily-Task-Manager a daily task manager application project created in flutter

This is a daily task manager application project created in flutter. Install this application on Android - Install from Play Store

DVS 0 May 10, 2022
Simple WebRTC for flutter (similar to the simple-peer project)

Simple WebRTC. Wraps flutter_webrtc similar to simple-peer IMPORTANT: Right now this library only supports data channels (and not media). Contribution

Simon Bengtsson 6 Nov 24, 2022
A simple screen that is shown when your app gets crashed instead of the normal crash dialog. It's very similar to the one in Flutter.

Red Screen Of Death What A simple screen that is shown when your app gets crashed instead of the normal crash dialog. It's very similar to the one in

Ahmad Melegy 178 Dec 9, 2022
Flutter package implements Sign Google redirect(working for incognito mode)

google_sign_in_web_redirect Flutter package implements Sign Google redirect(working for incognito mode). Usage Import the package dependencies: goog

null 2 Dec 15, 2022
A pure Dart package for working with RDF (resource description framework).

RDFLib A pure Dart package for working with RDF (resource description framework). Features Create triple instances (with data types) Create a graph to

null 5 Dec 15, 2022
This package helps developer to sort the flutter/dart packages and plugins alphabetically, This makes it easier when managing too many packages and when working with teams

Package helps to sort the flutter/dart packages and plugins alphabetically, This makes it easier when managing too many packages and when working with

DANCHE 7 Dec 21, 2022
Todo is an Simple Task Management App coded using Dart which is a peogramming language for Flutter SDK(2.5) supports Null Safety 📑🚩

Todo ?? ?? ?? Introduction Todo is an Simple Task Management App coded using Dart which is a peogramming language for Flutter SDK(2.5) supports Null S

navee-ramesh 6 Nov 5, 2022
A working Twitter clone written in Flutter using Firebase auth,realtime,firestore database and storage

A working Twitter clone written in Flutter using Firebase auth,realtime,firestore database and storage

The Github Mafia 17 Dec 24, 2022
A working Twitter clone built in Flutter using Firebase auth,realtime,firestore database and storage.

Fwitter - Twitter clone in flutter A working Twitter clone built in Flutter using Firebase auth,realtime,firestore database and storage. Dependencies

Dominique Rwema Bagirishya 31 Oct 5, 2022