CINXE.COM
Isolates | Dart
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="x-ua-compatible" content="ie=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><script>!function(e,t,a,n){e[n]=e[n]||[],e[n].push({"gtm.start":(new Date).getTime(),event:"gtm.js"});var g=t.getElementsByTagName(a)[0],m=t.createElement(a);m.async=!0,m.src="https://www.googletagmanager.com/gtm.js?id=GTM-5VSZM5J",g.parentNode.insertBefore(m,g)}(window,document,"script","dataLayer")</script><meta name="description" content="Information on writing isolates in Dart."><title>Isolates | Dart</title><link rel="icon" sizes="64x64" href="/assets/img/logo/dart-64.png" eleventy:ignore><link href="/assets/img/touch-icon-iphone.png" rel="apple-touch-icon" eleventy:ignore><link href="/assets/img/touch-icon-ipad.png" rel="apple-touch-icon" sizes="152x152" eleventy:ignore><link href="/assets/img/touch-icon-iphone-retina.png" rel="apple-touch-icon" sizes="180x180" eleventy:ignore><link href="/assets/img/touch-icon-ipad-retina.png" rel="apple-touch-icon" sizes="167x167" eleventy:ignore><meta name="twitter:card" content="summary"><meta name="twitter:site" content="@dart_lang"><meta name="twitter:title" content="Isolates"><meta name="twitter:description" content="Information on writing isolates in Dart."><meta property="og:title" content="Isolates"><meta property="og:description" content="Information on writing isolates in Dart."><meta property="og:url" content="/language/isolates/"><meta property="og:image" content="/assets/img/logo/dart-logo-for-shares.png?2" eleventy:ignore><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Display:wght@400&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Text:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" rel="stylesheet"><link rel="stylesheet" href="/assets/css/main.css"><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js" integrity="sha512-3gJwYpMe3QewGELv8k/BX9vcqhryRdzRMxVfq6ngyWXwo03GFEzjsUm8Q7RZcHPHksttq7/GFoxjCVUjkjvPdw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/js/bootstrap.min.js" integrity="sha384-+sLIOodYLS7CIrQpBjl+C7nPvqq+FbNUBDunl/OZv93DB7Ln/533i8e/mZXLi/P+" crossorigin="anonymous" referrerpolicy="no-referrer"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/3.0.5/js.cookie.min.js" integrity="sha512-nlp9/l96/EpjYBx7EP7pGASVXNe80hGhYAUrjeXnu/fyF5Py0/RXav4BBNs7n5Hx1WFhOEOWSAVjGeC3oKxDVQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script><script src="/assets/js/os-tabs.js"></script><script src="/assets/js/utilities.js"></script><script src="/assets/js/main.js"></script><script>!function(e,a,t,n,c,o,s){e.GoogleAnalyticsObject=c,e[c]=e[c]||function(){(e[c].q=e[c].q||[]).push(arguments)},e[c].l=1*new Date,o=a.createElement(t),s=a.getElementsByTagName(t)[0],o.async=1,o.src="//www.google-analytics.com/analytics.js",s.parentNode.insertBefore(o,s)}(window,document,"script",0,"ga"),ga("create","UA-26406144-4","auto"),ga("send","pageview")</script></head><body class="default.html show_banner"><a id="skip" href="#site-content-title">Skip to main content</a><section id="cookie-notice"><div class="container"><p>dart.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. <a href="https://policies.google.com/technologies/cookies" target="_blank" rel="noopener">Learn more</a>.</p><button id="cookie-consent" class="btn btn-primary">OK, got it</button></div></section><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5VSZM5J" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript><header id="page-header" class="site-header"><nav id="mainnav" class="site-header"><div id="menu-toggle"><i class="material-symbols">menu</i></div><a href="/" class="brand" title="Dart"><img src="/assets/img/logo/logo-white-text.svg" alt="Dart"></a><ul class="navbar"><li><a href="/overview" class="nav-link">Overview</a></li><li class="mainnav__get-started"><a href="/guides" class="nav-link active"><span>Docs</span></a></li><li><a href="/community" class="nav-link">Community</a></li><li><a href="/#try-dart" class="nav-link">Try Dart</a></li><li><a href="/get-dart" class="nav-link">Get Dart</a></li><li class="searchfield"><form action="/search" class="site-header__search form-inline" id="cse-search-box"><input type="hidden" name="cx" value="011220921317074318178:_yy-tmb5t_i"> <input type="hidden" name="ie" value="UTF-8"> <input type="hidden" name="hl" value="en"> <input class="site-header__searchfield form-control search-field" type="search" name="q" id="search-main" autocomplete="off" placeholder="Search" aria-label="Search"></form></li></ul></nav></header><div class="banner"><p class="banner__text">Announcing Dart 3.5 and an updated Dart roadmap! <a href="https://medium.com/dartlang/dart-3-5-6ca36259fa2f" target="_blank">Learn more</a></p></div><div id="sidenav"><form action="/search/" class="site-header__search form-inline"><input class="site-header__searchfield form-control search-field" type="search" name="q" id="search-side" autocomplete="off" placeholder="Search" aria-label="Search"></form><div class="site-sidebar"><ul class="navbar-nav"><li class="nav-item"><a href="/overview" class="nav-link">Overview</a></li><li class="nav-item"><a href="/community" class="nav-link">Community</a></li><li class="nav-item"><a href="https://dartpad.dev" class="nav-link">Try Dart</a></li><li class="nav-item"><a href="/get-dart" class="nav-link">Get Dart</a></li><li class="nav-item"><a href="/guides" class="nav-link">Docs</a></li><li aria-hidden="true"><div class="sidebar-primary-divider"></div></li></ul><ul class="nav flex-column"><li class="nav-item"><a class="nav-link active collapsible" data-toggle="collapse" href="#sidenav-1" role="button" aria-expanded="true" aria-controls="sidenav-1">Language</a><ul class="nav flex-column flex-nowrap collapse show" id="sidenav-1"><li class="nav-item"><a class="nav-link" href="/language">Introduction</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-1-2" href="#sidenav-1-2" role="button" aria-expanded="false" aria-controls="sidenav-1-2">Syntax basics</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-1-2"><li class="nav-item"><a class="nav-link" href="/language/variables">Variables</a></li><li class="nav-item"><a class="nav-link" href="/language/operators">Operators</a></li><li class="nav-item"><a class="nav-link" href="/language/comments">Comments</a></li><li class="nav-item"><a class="nav-link" href="/language/metadata">Metadata</a></li><li class="nav-item"><a class="nav-link" href="/language/libraries">Libraries & imports</a></li><li class="nav-item"><a class="nav-link" href="/language/keywords">Keywords</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-1-3" href="#sidenav-1-3" role="button" aria-expanded="false" aria-controls="sidenav-1-3">Types</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-1-3"><li class="nav-item"><a class="nav-link" href="/language/built-in-types">Built-in types</a></li><li class="nav-item"><a class="nav-link" href="/language/records">Records</a></li><li class="nav-item"><a class="nav-link" href="/language/collections">Collections</a></li><li class="nav-item"><a class="nav-link" href="/language/generics">Generics</a></li><li class="nav-item"><a class="nav-link" href="/language/typedefs">Typedefs</a></li><li class="nav-item"><a class="nav-link" href="/language/type-system">Type system</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-1-4" href="#sidenav-1-4" role="button" aria-expanded="false" aria-controls="sidenav-1-4">Patterns</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-1-4"><li class="nav-item"><a class="nav-link" href="/language/patterns">Overview & usage</a></li><li class="nav-item"><a class="nav-link" href="/language/pattern-types">Pattern types</a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/dart-patterns-records" target="_blank" rel="noopener">Applied tutorial</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/language/functions">Functions</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-1-6" href="#sidenav-1-6" role="button" aria-expanded="false" aria-controls="sidenav-1-6">Control flow</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-1-6"><li class="nav-item"><a class="nav-link" href="/language/loops">Loops</a></li><li class="nav-item"><a class="nav-link" href="/language/branches">Branches</a></li><li class="nav-item"><a class="nav-link" href="/language/error-handling">Error handling</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-1-7" href="#sidenav-1-7" role="button" aria-expanded="false" aria-controls="sidenav-1-7">Classes & objects</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-1-7"><li class="nav-item"><a class="nav-link" href="/language/classes">Classes</a></li><li class="nav-item"><a class="nav-link" href="/language/constructors">Constructors</a></li><li class="nav-item"><a class="nav-link" href="/language/methods">Methods</a></li><li class="nav-item"><a class="nav-link" href="/language/extend">Extend a class</a></li><li class="nav-item"><a class="nav-link" href="/language/mixins">Mixins</a></li><li class="nav-item"><a class="nav-link" href="/language/enums">Enums</a></li><li class="nav-item"><a class="nav-link" href="/language/extension-methods">Extension methods</a></li><li class="nav-item"><a class="nav-link" href="/language/extension-types">Extension types</a></li><li class="nav-item"><a class="nav-link" href="/language/callable-objects">Callable objects</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-1-8" href="#sidenav-1-8" role="button" aria-expanded="false" aria-controls="sidenav-1-8">Class modifiers</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-1-8"><li class="nav-item"><a class="nav-link" href="/language/class-modifiers">Overview & usage</a></li><li class="nav-item"><a class="nav-link" href="/language/class-modifiers-for-apis">Class modifiers for API maintainers</a></li><li class="nav-item"><a class="nav-link" href="/language/modifier-reference">Reference</a></li></ul></li><li class="nav-item"><a class="nav-link active collapsible" data-toggle="collapse" data-target="#sidenav-1-9" href="#sidenav-1-9" role="button" aria-expanded="true" aria-controls="sidenav-1-9">Concurrency</a><ul class="nav flex-column flex-nowrap collapse show" id="sidenav-1-9"><li class="nav-item"><a class="nav-link" href="/language/concurrency">Overview</a></li><li class="nav-item"><a class="nav-link" href="/language/async">Asynchronous support</a></li><li class="nav-item"><a class="nav-link active" href="/language/isolates">Isolates</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-1-10" href="#sidenav-1-10" role="button" aria-expanded="false" aria-controls="sidenav-1-10">Null safety</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-1-10"><li class="nav-item"><a class="nav-link" href="/null-safety">Sound null safety</a></li><li class="nav-item"><a class="nav-link" href="/null-safety/migration-guide">Migrating to null safety</a></li><li class="nav-item"><a class="nav-link" href="/null-safety/understanding-null-safety">Understanding null safety</a></li><li class="nav-item"><a class="nav-link" href="/null-safety/unsound-null-safety">Unsound null safety</a></li><li class="nav-item"><a class="nav-link" href="/null-safety/faq">FAQ</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#sidenav-2" role="button" aria-expanded="false" aria-controls="sidenav-2">Core libraries</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-2"><li class="nav-item"><a class="nav-link" href="/libraries">Overview</a></li><li class="nav-item"><a class="nav-link" href="/libraries/dart-core">dart:core</a></li><li class="nav-item"><a class="nav-link" href="/libraries/dart-async">dart:async</a></li><li class="nav-item"><a class="nav-link" href="/libraries/dart-math">dart:math</a></li><li class="nav-item"><a class="nav-link" href="/libraries/dart-convert">dart:convert</a></li><li class="nav-item"><a class="nav-link" href="/libraries/dart-io">dart:io</a></li><li class="nav-item"><a class="nav-link" href="/libraries/dart-html">dart:html</a></li><div class="dropdown-divider"></div><li class="nav-item"><a class="nav-link" href="/libraries/collections/iterables">Iterable collections</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-2-10" href="#sidenav-2-10" role="button" aria-expanded="false" aria-controls="sidenav-2-10">Asynchronous programming</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-2-10"><li class="nav-item"><a class="nav-link" href="/libraries/async/async-await">Tutorial</a></li><li class="nav-item"><a class="nav-link" href="/libraries/async/futures-error-handling">Futures and error handling</a></li><li class="nav-item"><a class="nav-link" href="/libraries/async/using-streams">Using streams</a></li><li class="nav-item"><a class="nav-link" href="/libraries/async/creating-streams">Creating streams</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#sidenav-3" role="button" aria-expanded="false" aria-controls="sidenav-3">Effective Dart</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-3"><li class="nav-item"><a class="nav-link" href="/effective-dart">Overview</a></li><li class="nav-item"><a class="nav-link" href="/effective-dart/style">Style</a></li><li class="nav-item"><a class="nav-link" href="/effective-dart/documentation">Documentation</a></li><li class="nav-item"><a class="nav-link" href="/effective-dart/usage">Usage</a></li><li class="nav-item"><a class="nav-link" href="/effective-dart/design">Design</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#sidenav-4" role="button" aria-expanded="false" aria-controls="sidenav-4">Packages</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-4"><li class="nav-item"><a class="nav-link" href="/tools/pub/packages">How to use packages</a></li><li class="nav-item"><a class="nav-link" href="/resources/useful-packages">Commonly used packages</a></li><li class="nav-item"><a class="nav-link" href="/guides/libraries/create-packages">Creating packages</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/publishing">Publishing packages</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/writing-package-pages">Writing package pages</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-4-6" href="#sidenav-4-6" role="button" aria-expanded="false" aria-controls="sidenav-4-6">Package reference</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-4-6"><li class="nav-item"><a class="nav-link" href="/tools/pub/dependencies">Dependencies</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/glossary">Glossary</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/package-layout">Package layout conventions</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/environment-variables">Pub environment variables</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/pubspec">Pubspec file</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/troubleshoot">Troubleshooting pub</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/verified-publishers">Verified publishers</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/security-advisories">Security advisories</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/versioning">Versioning</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/custom-package-repositories">Custom package repositories</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/guides/libraries/private-files">What not to commit</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#sidenav-5" role="button" aria-expanded="false" aria-controls="sidenav-5">Development</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-5"><li class="nav-item"><a class="nav-link" href="/guides/json">JSON</a></li><li class="nav-item"><a class="nav-link" href="/guides/language/numbers">Number representation</a></li><li class="nav-item"><a class="nav-link" href="/resources/google-apis">Google APIs</a></li><li class="nav-item"><a class="nav-link" href="/multiplatform-apps">Multi-platform apps</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-5" href="#sidenav-5-5" role="button" aria-expanded="false" aria-controls="sidenav-5-5">Command-line & server apps</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-5-5"><li class="nav-item"><a class="nav-link" href="/server">Overview</a></li><li class="nav-item"><a class="nav-link" href="/tutorials/server/get-started">Get started</a></li><li class="nav-item"><a class="nav-link" href="/tutorials/server/cmdline">Write command-line apps</a></li><li class="nav-item"><a class="nav-link" href="/tutorials/server/fetch-data">Fetch data from the internet</a></li><li class="nav-item"><a class="nav-link" href="/tutorials/server/httpserver">Write HTTP servers</a></li><li class="nav-item"><a class="nav-link" href="/server/libraries">Libraries & packages</a></li><li class="nav-item"><a class="nav-link" href="/server/google-cloud">Google Cloud</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-6" href="#sidenav-5-6" role="button" aria-expanded="false" aria-controls="sidenav-5-6">Web apps</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-5-6"><li class="nav-item"><a class="nav-link" href="/web">Overview</a></li><li class="nav-item"><a class="nav-link" href="/web/get-started">Get started</a></li><li class="nav-item"><a class="nav-link" href="/web/deployment">Deployment</a></li><li class="nav-item"><a class="nav-link" href="/web/libraries">Libraries & packages</a></li><li class="nav-item"><a class="nav-link" href="/web/wasm">Wasm compilation</a></li></ul></li><li class="nav-item"><a class="nav-link" href="/guides/environment-declarations">Environment declarations</a></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#sidenav-6" role="button" aria-expanded="false" aria-controls="sidenav-6">Interoperability</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-6"><li class="nav-item"><a class="nav-link" href="/interop/c-interop">C interop</a></li><li class="nav-item"><a class="nav-link" href="/interop/objective-c-interop">Objective-C & Swift interop</a></li><li class="nav-item"><a class="nav-link" href="/interop/java-interop">Java & Kotlin interop</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-6-4" href="#sidenav-6-4" role="button" aria-expanded="false" aria-controls="sidenav-6-4">JavaScript interop</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-6-4"><li class="nav-item"><a class="nav-link" href="/interop/js-interop">Overview</a></li><li class="nav-item"><a class="nav-link" href="/interop/js-interop/usage">Usage</a></li><li class="nav-item"><a class="nav-link" href="/interop/js-interop/js-types">JS types</a></li><li class="nav-item"><a class="nav-link" href="/interop/js-interop/tutorials">Tutorials</a></li><li class="nav-item"><a class="nav-link" href="/interop/js-interop/past-js-interop">Past JS interop</a></li><div class="dropdown-divider"></div><li class="nav-item"><a class="nav-link" href="/interop/js-interop/package-web">Web interop</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#sidenav-7" role="button" aria-expanded="false" aria-controls="sidenav-7">Tools & techniques</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-7"><li class="nav-item"><a class="nav-link" href="/tools">Overview</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-7-2" href="#sidenav-7-2" role="button" aria-expanded="false" aria-controls="sidenav-7-2">Editors & debuggers</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-7-2"><li class="nav-item"><a class="nav-link" href="/tools/jetbrains-plugin">IntelliJ & Android Studio</a></li><li class="nav-item"><a class="nav-link" href="/tools/vs-code">VS Code</a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-devtools">Dart DevTools</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-7-2-4" href="#sidenav-7-2-4" role="button" aria-expanded="false" aria-controls="sidenav-7-2-4">DartPad</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-7-2-4"><li class="nav-item"><a class="nav-link" href="/tools/dartpad">Overview</a></li><li class="nav-item"><a class="nav-link" href="/tools/dartpad/troubleshoot">Troubleshooting DartPad</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-7-3" href="#sidenav-7-3" role="button" aria-expanded="false" aria-controls="sidenav-7-3">Command-line tools</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-7-3"><li class="nav-item"><a class="nav-link collapsible" data-toggle="collapse" data-target="#sidenav-7-3-1" href="#sidenav-7-3-1" role="button" aria-expanded="true" aria-controls="sidenav-7-3-1">Dart SDK</a><ul class="nav flex-column flex-nowrap collapse show" id="sidenav-7-3-1"><li class="nav-item"><a class="nav-link" href="/tools/sdk">Overview</a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-tool">dart</a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-analyze">dart analyze</a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-compile">dart compile</a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-create">dart create</a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-doc">dart doc</a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-fix">dart fix</a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-format">dart format</a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-info">dart info</a></li><li class="nav-item"><a class="nav-link" href="/tools/pub/cmd">dart pub</a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-run">dart run</a></li><li class="nav-item"><a class="nav-link" href="/tools/dart-test">dart test</a></li><li class="nav-item"><a class="nav-link" href="/tools/dartaotruntime">dartaotruntime</a></li><li class="nav-item"><a class="nav-link" href="/tools/experiment-flags">Experiment flags</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible" data-toggle="collapse" data-target="#sidenav-7-3-2" href="#sidenav-7-3-2" role="button" aria-expanded="true" aria-controls="sidenav-7-3-2">Other command-line tools</a><ul class="nav flex-column flex-nowrap collapse show" id="sidenav-7-3-2"><li class="nav-item"><a class="nav-link" href="/tools/build_runner">build_runner</a></li><li class="nav-item"><a class="nav-link" href="/tools/webdev">webdev</a></li></ul></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-7-4" href="#sidenav-7-4" role="button" aria-expanded="false" aria-controls="sidenav-7-4">Static analysis</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-7-4"><li class="nav-item"><a class="nav-link" href="/tools/analysis">Customizing static analysis</a></li><li class="nav-item"><a class="nav-link" href="/guides/language/sound-problems">Fixing common type problems</a></li><li class="nav-item"><a class="nav-link" href="/tools/non-promotion-reasons">Fixing type promotion failures</a></li><li class="nav-item"><a class="nav-link" href="/tools/linter-rules">Linter rules</a></li><li class="nav-item"><a class="nav-link" href="/tools/diagnostic-messages">Diagnostic messages</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-7-5" href="#sidenav-7-5" role="button" aria-expanded="false" aria-controls="sidenav-7-5">Testing & optimization</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-7-5"><li class="nav-item"><a class="nav-link" href="/guides/testing">Testing</a></li><li class="nav-item"><a class="nav-link" href="/web/debugging">Debugging web apps</a></li></ul></li></ul></li><li aria-hidden="true"><div class="sidebar-primary-divider"></div></li><li class="nav-item"><a class="nav-link collapsed collapsible" data-toggle="collapse" href="#sidenav-9" role="button" aria-expanded="false" aria-controls="sidenav-9">Resources</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-9"><li class="nav-item"><a class="nav-link" href="/resources/dart-cheatsheet">Language cheatsheet</a></li><li class="nav-item"><a class="nav-link" href="/resources/breaking-changes">Breaking changes</a></li><li class="nav-item"><a class="nav-link" href="/guides/language/evolution">Language evolution</a></li><li class="nav-item"><a class="nav-link" href="/guides/language/spec">Language specification</a></li><li class="nav-item"><a class="nav-link" href="/resources/dart-3-migration">Dart 3 migration guide</a></li><li class="nav-item"><a class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-9-6" href="#sidenav-9-6" role="button" aria-expanded="false" aria-controls="sidenav-9-6">Coming from ...</a><ul class="nav flex-column flex-nowrap collapse" id="sidenav-9-6"><li class="nav-item"><a class="nav-link" href="/resources/coming-from/js-to-dart">JavaScript to Dart</a></li><li class="nav-item"><a class="nav-link" href="/resources/coming-from/swift-to-dart">Swift to Dart</a></li></ul></li><div class="dropdown-divider"></div><li class="nav-item"><a class="nav-link" href="/resources/faq">FAQ</a></li><li class="nav-item"><a class="nav-link" href="/resources/glossary">Glossary</a></li><li class="nav-item"><a class="nav-link" href="/resources/books">Books</a></li><li class="nav-item"><a class="nav-link" href="/resources/videos">Videos</a></li><li class="nav-item"><a class="nav-link" href="/tutorials">Tutorials</a></li></ul></li><li class="nav-item"><a class="nav-link collapsible" data-toggle="collapse" href="#sidenav-10" role="button" aria-expanded="true" aria-controls="sidenav-10">Related sites</a><ul class="nav flex-column flex-nowrap collapse show" id="sidenav-10"><li class="nav-item"><a class="nav-link" href="https://api.dart.dev" target="_blank" rel="noopener">API reference</a></li><li class="nav-item"><a class="nav-link" href="https://medium.com/dartlang" target="_blank" rel="noopener">Blog</a></li><li class="nav-item"><a class="nav-link" href="https://dartpad.dev" target="_blank" rel="noopener">DartPad (online editor)</a></li><li class="nav-item"><a class="nav-link" href="https://flutter.dev" target="_blank" rel="noopener">Flutter</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev" target="_blank" rel="noopener">Package site</a></li></ul></li></ul></div></div><main id="page-content"><div id="site-toc--side" class="site-toc"><header class="site-toc__title">Contents</header><ul class="section-nav"><li class="toc-entry nav-item"><a class="nav-link" href="#implementing-a-simple-worker-isolate">Implementing a simple worker isolate</a><ul class="nav"><li class="toc-entry nav-item"><a class="nav-link" href="#running-an-existing-method-in-a-new-isolate">Running an existing method in a new isolate</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#sending-closures-with-isolates">Sending closures with isolates</a></li></ul></li><li class="toc-entry nav-item"><a class="nav-link" href="#sending-multiple-messages-between-isolates-with-ports">Sending multiple messages between isolates with ports</a><ul class="nav"><li class="toc-entry nav-item"><a class="nav-link" href="#receiveport-and-sendport">ReceivePort and SendPort</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#basic-ports-example">Basic ports example</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#robust-ports-example">Robust ports example</a></li></ul></li></ul></div><article><div class="content"><nav id="subnav"><ul><li class="previous"><a href="/language/async">⟨ Asynchronous support</a></li><li class="next"><a href="/null-safety">Sound Null Safety ⟩</a></li></ul></nav><div id="site-content-title"><h1>Isolates</h1></div><div id="site-toc--inline" class="site-toc"><header class="site-toc__title">Contents</header><ul class="section-nav"><li class="toc-entry"><a href="#implementing-a-simple-worker-isolate">Implementing a simple worker isolate</a><ul><li class="toc-entry"><a href="#running-an-existing-method-in-a-new-isolate">Running an existing method in a new isolate</a></li><li class="toc-entry"><a href="#sending-closures-with-isolates">Sending closures with isolates</a></li></ul></li><li class="toc-entry"><a href="#sending-multiple-messages-between-isolates-with-ports">Sending multiple messages between isolates with ports</a><ul><li class="toc-entry"><a href="#receiveport-and-sendport">ReceivePort and SendPort</a></li><li class="toc-entry"><a href="#basic-ports-example">Basic ports example</a></li><li class="toc-entry"><a href="#robust-ports-example">Robust ports example</a></li></ul></li></ul></div> <?code-excerpt path-base="concurrency"?> <style>article img { padding: 15px 0; }</style><p>This page discusses some examples that use the <code>Isolate</code> API to implement isolates.</p><p>You should use isolates whenever your application is handling computations that are large enough to temporarily block other computations. The most common example is in <a href="https://docs.flutter.dev/perf/isolates">Flutter</a> applications, when you need to perform large computations that might otherwise cause the UI to become unresponsive.</p><p>There aren't any rules about when you <em>must</em> use isolates, but here are some more situations where they can be useful:</p><ul><li>Parsing and decoding exceptionally large JSON blobs.</li><li>Processing and compressing photos, audio and video.</li><li>Converting audio and video files.</li><li>Performing complex searching and filtering on large lists or within file systems.</li><li>Performing I/O, such as communicating with a database.</li><li>Handling a large volume of network requests.</li></ul><div class="header-wrapper"><h2 id="implementing-a-simple-worker-isolate">Implementing a simple worker isolate</h2><a class="heading-link" href="#implementing-a-simple-worker-isolate" aria-label="Link to 'Implementing a simple worker isolate' section">#</a></div><p>These examples implement a main isolate that spawns a simple worker isolate. <a href="https://api.dart.dev/dart-isolate/Isolate/run.html"><code>Isolate.run()</code></a> simplifies the steps behind setting up and managing worker isolates:</p><ol><li>Spawns (starts and creates) an isolate.</li><li>Runs a function on the spawned isolate.</li><li>Captures the result.</li><li>Returns the result to the main isolate.</li><li>Terminates the isolate once work is complete.</li><li>Checks, captures, and throws exceptions and errors back to the main isolate.</li></ol><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">flutter</i> <span>Flutter note</span></div><div class="alert-content"><p>If you're using Flutter, you can use <a href="https://api.flutter.dev/flutter/foundation/compute.html">Flutter's <code>compute</code> function</a> instead of <code>Isolate.run()</code>.</p></div></aside><div class="header-wrapper"><h3 id="running-an-existing-method-in-a-new-isolate">Running an existing method in a new isolate</h3><a class="heading-link" href="#running-an-existing-method-in-a-new-isolate" aria-label="Link to 'Running an existing method in a new isolate' section">#</a></div><ol><li>Call <code>run()</code> to spawn a new isolate (a <a href="/language/concurrency#background-workers">background worker</a>), directly in the <a href="/language/concurrency#the-main-isolate">main isolate</a> while <code>main()</code> waits for the result:</li></ol> <?code-excerpt "lib/simple_worker_isolate.dart (main)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">const</span><span style="color:#0468D7"> String</span><span style="color:#222222"> filename = </span><span style="color:#11796D">'with_keys.json'</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // Read some data.</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> jsonData = </span><span style="color:#D43324">await</span><span style="color:#0468D7"> Isolate</span><span style="color:#222222">.</span><span style="color:#6200EE">run</span><span style="color:#222222">(_readAndParseJson);</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // Use that data.</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(</span><span style="color:#11796D">'Number of JSON keys: </span><span style="color:#11796D">${</span><span style="color:#222222">jsonData</span><span style="color:#11796D">.</span><span style="color:#222222">length</span><span style="color:#11796D">}</span><span style="color:#11796D">'</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><ol start="2"><li>Pass the worker isolate the function you want it to execute as its first argument. In this example, it's the existing function <code>_readAndParseJson()</code>:</li></ol> <?code-excerpt "lib/simple_worker_isolate.dart (spawned)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>> </span><span style="color:#6200EE">_readAndParseJson</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> fileData = </span><span style="color:#D43324">await</span><span style="color:#0468D7"> File</span><span style="color:#222222">(filename).</span><span style="color:#6200EE">readAsString</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> jsonData = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(fileData) </span><span style="color:#D43324">as</span><span style="color:#0468D7"> Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>;</span></span> <span class="line"><span style="color:#D43324"> return</span><span style="color:#222222"> jsonData;</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><ol start="3"><li><p><code>Isolate.run()</code> takes the result <code>_readAndParseJson()</code> returns and sends the value back to the main isolate, shutting down the worker isolate.</p></li><li><p>The worker isolate <em>transfers</em> the memory holding the result to the main isolate. It <em>does not copy</em> the data. The worker isolate performs a verification pass to ensure the objects are allowed to be transferred.</p></li></ol><p><code>_readAndParseJson()</code> is an existing, asynchronous function that could just as easily run directly in the main isolate. Using <code>Isolate.run()</code> to run it instead enables concurrency. The worker isolate completely abstracts the computations of <code>_readAndParseJson()</code>. It can complete without blocking the main isolate.</p><p>The result of <code>Isolate.run()</code> is always a Future, because code in the main isolate continues to run. Whether the computation the worker isolate executes is synchronous or asynchronous doesn't impact the main isolate, because it's running concurrently either way.</p><p>For the complete program, check out the <a href="https://github.com/dart-lang/samples/blob/main/isolates/bin/send_and_receive.dart">send_and_receive.dart</a> sample.</p><div class="header-wrapper"><h3 id="sending-closures-with-isolates">Sending closures with isolates</h3><a class="heading-link" href="#sending-closures-with-isolates" aria-label="Link to 'Sending closures with isolates' section">#</a></div><p>You can also create a simple worker isolate with <code>run()</code> using a function literal, or closure, directly in the main isolate.</p> <?code-excerpt "lib/simple_isolate_closure.dart (worker)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">const</span><span style="color:#0468D7"> String</span><span style="color:#222222"> filename = </span><span style="color:#11796D">'with_keys.json'</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // Read some data.</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> jsonData = </span><span style="color:#D43324">await</span><span style="color:#0468D7"> Isolate</span><span style="color:#222222">.</span><span style="color:#6200EE">run</span><span style="color:#222222">(() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> fileData = </span><span style="color:#D43324">await</span><span style="color:#0468D7"> File</span><span style="color:#222222">(filename).</span><span style="color:#6200EE">readAsString</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> jsonData = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(fileData) </span><span style="color:#D43324">as</span><span style="color:#0468D7"> Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>;</span></span> <span class="line"><span style="color:#D43324"> return</span><span style="color:#222222"> jsonData;</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // Use that data.</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(</span><span style="color:#11796D">'Number of JSON keys: </span><span style="color:#11796D">${</span><span style="color:#222222">jsonData</span><span style="color:#11796D">.</span><span style="color:#222222">length</span><span style="color:#11796D">}</span><span style="color:#11796D">'</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>This example accomplishes the same as the previous. A new isolate spawns, computes something, and sends back the result.</p><p>However, now the isolate sends a <a href="/language/functions#anonymous-functions">closure</a>. Closures are less limited than typical named functions, both in how they function and how they're written into the code. In this example, <code>Isolate.run()</code> executes what looks like local code, concurrently. In that sense, you can imagine <code>run()</code> to work like a control flow operator for "run in parallel".</p><div class="header-wrapper"><h2 id="sending-multiple-messages-between-isolates-with-ports">Sending multiple messages between isolates with ports</h2><a class="heading-link" href="#sending-multiple-messages-between-isolates-with-ports" aria-label="Link to 'Sending multiple messages between isolates with ports' section">#</a></div><p>Short-lived isolates are convenient to use, but require performance overhead to spawn new isolates and to copy objects from one isolate to another. If your code relies on repeatedly running the same computation using <code>Isolate.run</code>, you might improve performance by instead creating long-lived isolates that don’t exit immediately.</p><p>To do this, you can use some of the low-level isolate APIs that <code>Isolate.run</code> abstracts:</p><ul><li><a href="https://api.dart.dev/dart-isolate/Isolate/spawn.html"><code>Isolate.spawn()</code></a> and <a href="https://api.dart.dev/dart-isolate/Isolate/exit.html"><code>Isolate.exit()</code></a></li><li><a href="https://api.dart.dev/dart-isolate/ReceivePort-class.html"><code>ReceivePort</code></a> and <a href="https://api.dart.dev/dart-isolate/SendPort-class.html"><code>SendPort</code></a></li><li><a href="https://api.dart.dev/dart-isolate/SendPort/send.html"><code>SendPort.send()</code> method</a></li></ul><p>This section goes over the steps required to establish 2-way communication between a newly spawned isolate and the <a href="/language/concurrency#the-main-isolate">main isolate</a>. The first example, <a href="#basic-ports-example">Basic ports</a>, introduces the process at a high-level. The second example, <a href="#robust-ports-example">Robust ports</a>, gradually adds more practical, real-world functionality to the first.</p><div class="header-wrapper"><h3 id="receiveport-and-sendport"><code>ReceivePort</code> and <code>SendPort</code></h3><a class="heading-link" href="#receiveport-and-sendport" aria-label="Link to 'ReceivePort and SendPort' section">#</a></div><p>Setting up long-lived communication between isolates requires two classes (in addition to <code>Isolate</code>): <code>ReceivePort</code> and <code>SendPort</code>. These ports are the only way isolates can communicate with each other.</p><p>A <code>ReceivePort</code> is an object that handles messages that are sent from other isolates. Those messages are sent via a <code>SendPort</code>.</p><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>A <code>SendPort</code> object is associated with exactly one <code>ReceivePort</code>, but a single <code>ReceivePort</code> can have many <code>SendPorts</code>. When you create a <code>ReceivePort</code>, it creates a <code>SendPort</code> for itself. You can create additional <code>SendPorts</code> that can send messages to an existing <code>ReceivePort</code>.</p></div></aside><p>Ports behave similarly to <a href="https://api.dart.dev/dart-async/Stream-class.html"><code>Stream</code></a> objects (in fact, receive ports implement <code>Stream</code>!) You can think of a <code>SendPort</code> and <code>ReceivePort</code> like Stream's <code>StreamController</code> and listeners, respectively. A <code>SendPort</code> is like a <code>StreamController</code> because you "add" messages to them with the <a href="https://api.dart.dev/dart-isolate/SendPort/send.html"><code>SendPort.send()</code> method</a>, and those messages are handled by a listener, in this case the <code>ReceivePort</code>. The <code>ReceivePort</code> then handles the messages it receives by passing them as arguments to a callback that you provide.</p><div class="header-wrapper"><h4 id="setting-up-ports">Setting up ports</h4><a class="heading-link" href="#setting-up-ports" aria-label="Link to 'Setting up ports' section">#</a></div><p>A newly spawned isolate only has the information it receives through the <code>Isolate.spawn</code> call. If you need the main isolate to continue to communicate with a spawned isolate past its initial creation, you must set up a communication channel where the spawned isolate can send messages to the main isolate. Isolates can only communicate via message passing. They can’t “see” inside each others’ memory, which is where the name “isolate” comes from.</p><p>To set up this 2-way communication, first create a <a href="https://api.dart.dev/dart-isolate/ReceivePort-class.html"><code>ReceivePort</code></a> in the main isolate, then pass its <a href="https://api.dart.dev/dart-isolate/SendPort-class.html"><code>SendPort</code></a> as an argument to the new isolate when spawning it with <code>Isolate.spawn</code>. The new isolate then creates its own <code>ReceivePort</code>, and sends <em>its</em> <code>SendPort</code> back on the <code>SendPort</code> it was passed by the main isolate. The main isolate receives this <code>SendPort</code>, and now both sides have an open channel to send and receive messages.</p><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>The diagrams in this section are high-level and intended to convey the <em>concept</em> of using ports for isolates. Actual implementation requires a bit more code, which you will find <a href="#basic-ports-example">later on this page</a>.</p></div></aside><p><img src="/assets/img/language/concurrency/ports-setup.png" alt="A figure showing events being fed, one by one, into the event loop"></p><ol><li>Create a <code>ReceivePort</code> in the main isolate. The <code>SendPort</code> is created automatically as a property on the <code>ReceivePort</code>.</li><li>Spawn the worker isolate with <code>Isolate.spawn()</code></li><li>Pass a reference to <code>ReceivePort.sendPort</code> as the first message to the worker isolate.</li><li>Create another new <code>ReceivePort</code> in the worker isolate.</li><li>Pass a reference to the worker isolate's <code>ReceivePort.sendPort</code> as the first message <em>back</em> to the main isolate.</li></ol><p>Along with creating the ports and setting up communication, you’ll also need to tell the ports what to do when they receive messages. This is done using the <code>listen</code> method on each respective <code>ReceivePort</code>.</p><p><img src="/assets/img/language/concurrency/ports-passing-messages.png" alt="A figure showing events being fed, one by one, into the event loop"></p><ol><li>Send a message via the main isolate’s reference to the worker isolate's <code>SendPort</code>.</li><li>Receive and handle the message via a listener on the worker isolate's <code>ReceivePort</code>. This is where the computation you want to move off the main isolate is executed.</li><li>Send a return message via the worker isolate's reference to the main isolate's <code>SendPort</code>.</li><li>Receive the message via a listener on the main isolate's <code>ReceivePort</code>.</li></ol><div class="header-wrapper"><h3 id="basic-ports-example">Basic ports example</h3><a class="heading-link" href="#basic-ports-example" aria-label="Link to 'Basic ports example' section">#</a></div><p>This example demonstrates how you can set up a long-lived worker isolate with 2-way communication between it and the main isolate. The code uses the example of sending JSON text to a new isolate, where the JSON will be parsed and decoded, before being sent back to the main isolate.</p><aside class="alert alert-warning"><div class="alert-header"><i class="material-symbols" aria-hidden="true">warning</i> <span>Warning</span></div><div class="alert-content"><p>This example is meant to teach the <em>bare minimum</em> needed to spawn a new isolate that can send and receive multiple messages over time.</p><p>It does not cover important pieces of functionality that are expected in production software, like error handling, shutting down ports, and message sequencing.</p><p>The <a href="#robust-ports-example">Robust ports example</a> in the next section covers this functionality and discusses some of the issues that can arise without it.</p></div></aside><div class="header-wrapper"><h4 id="step-1-define-the-worker-class">Step 1: Define the worker class</h4><a class="heading-link" href="#step-1-define-the-worker-class" aria-label="Link to 'Step 1: Define the worker class' section">#</a></div><p>First, create a class for your background worker isolate. This class contains all the functionality you need to:</p><ul><li>Spawn an isolate.</li><li>Send messages to that isolate.</li><li>Have the isolate decode some JSON.</li><li>Send the decoded JSON back to the main isolate.</li></ul><p>The class exposes two public methods: one that spawns the worker isolate, and one that handles sending messages to that worker isolate.</p><p>The remaining sections in this example will show you how to fill in the class methods, one-by-one.</p> <?code-excerpt "lib/basic_ports_example/start.dart (worker)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">class</span><span style="color:#0468D7"> Worker</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#D43324">void</span><span style="color:#222222">> </span><span style="color:#6200EE">spawn</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Add functionality to spawn a worker isolate.</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> void</span><span style="color:#6200EE"> _handleResponsesFromIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">dynamic</span><span style="color:#222222"> message) {</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Handle messages sent back from the worker isolate.</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> static</span><span style="color:#D43324"> void</span><span style="color:#6200EE"> _startRemoteIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> port) {</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Define code that should be executed on the worker isolate.</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#D43324">void</span><span style="color:#222222">> </span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#0468D7">String</span><span style="color:#222222"> message) </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Define a public method that can</span></span> <span class="line"><span style="color:#6E6E70"> // be used to send messages to the worker isolate.</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><div class="header-wrapper"><h4 id="step-2-spawn-a-worker-isolate">Step 2: Spawn a worker isolate</h4><a class="heading-link" href="#step-2-spawn-a-worker-isolate" aria-label="Link to 'Step 2: Spawn a worker isolate' section">#</a></div><p>The <code>Worker.spawn</code> method is where you will group the code for creating the worker isolate and ensuring it can receive and send messages.</p><ul><li>First, create a <code>ReceivePort</code>. This allows the main isolate to receive messages sent from the newly spawned worker isolate.</li><li>Next, add a listener to the receive port to handle messages the worker isolate will send back. The callback passed to the listener, <code>_handleResponsesFromIsolate</code>, will be covered in <a href="#step-4-handle-messages-on-the-main-isolate">step 4</a>.</li><li>Finally, spawn the worker isolate with <code>Isolate.spawn</code>. It expects two arguments: a function to be executed on the worker isolate (covered in <a href="#step-3-execute-code-on-the-worker-isolate">step 3</a>), and the <code>sendPort</code> property of the receive port.</li></ul> <?code-excerpt "lib/basic_ports_example/complete.dart (spawn)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#D43324">void</span><span style="color:#222222">> </span><span style="color:#6200EE">spawn</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> receivePort = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> receivePort.</span><span style="color:#6200EE">listen</span><span style="color:#222222">(_handleResponsesFromIsolate);</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#0468D7"> Isolate</span><span style="color:#222222">.</span><span style="color:#6200EE">spawn</span><span style="color:#222222">(_startRemoteIsolate, receivePort.sendPort);</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>The <code>receivePort.sendPort</code> argument will be passed to the callback (<code>_startRemoteIsolate</code>) as an argument when it’s called on the worker isolate. This is the first step in ensuring that the worker isolate has a way to send messages back to the main isolate.</p><div class="header-wrapper"><h4 id="step-3-execute-code-on-the-worker-isolate">Step 3: Execute code on the worker isolate</h4><a class="heading-link" href="#step-3-execute-code-on-the-worker-isolate" aria-label="Link to 'Step 3: Execute code on the worker isolate' section">#</a></div><p>In this step, you define the method <code>_startRemoteIsolate</code> that is sent to the worker isolate to be executed when it spawns. This method is like the “main” method for the worker isolate.</p><ul><li>First, create another new <code>ReceivePort</code>. This port receives future messages from the main isolate.</li><li>Next, send that port’s <code>SendPort</code> back to the main isolate.</li><li>Finally, add a listener to the new <code>ReceivePort</code>. This listener handles messages the main isolate sends to the worker isolate.</li></ul> <?code-excerpt "lib/basic_ports_example/complete.dart (start-remote-isolate)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">static</span><span style="color:#D43324"> void</span><span style="color:#6200EE"> _startRemoteIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> port) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> receivePort = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> port.</span><span style="color:#6200EE">send</span><span style="color:#222222">(receivePort.sendPort);</span></span> <span class="line"></span> <span class="line"><span style="color:#222222"> receivePort.</span><span style="color:#6200EE">listen</span><span style="color:#222222">((</span><span style="color:#0468D7">dynamic</span><span style="color:#222222"> message) </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (message is </span><span style="color:#0468D7">String</span><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> transformed = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(message);</span></span> <span class="line"><span style="color:#222222"> port.</span><span style="color:#6200EE">send</span><span style="color:#222222">(transformed);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>The listener on the worker’s <code>ReceivePort</code> decodes the JSON passed from the main isolate, and then sends the decoded JSON back to the main isolate.</p><p>This listener is the entry point for messages sent from the main isolate to the worker isolate. <strong>This is the only chance you have to tell the worker isolate what code to execute in the future.</strong></p><div class="header-wrapper"><h4 id="step-4-handle-messages-on-the-main-isolate">Step 4: Handle messages on the main isolate</h4><a class="heading-link" href="#step-4-handle-messages-on-the-main-isolate" aria-label="Link to 'Step 4: Handle messages on the main isolate' section">#</a></div><p>Finally, you need to tell the main isolate how to handle messages sent from the worker isolate back to the main isolate. To do so, you need to fill in the <code>_handleResponsesFromIsolate</code> method. Recall that this method is passed to the <code>receivePort.listen</code> method, as described in <a href="#step-2-spawn-a-worker-isolate">step 2</a>:</p> <?code-excerpt "lib/basic_ports_example/complete.dart (spawn)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#D43324">void</span><span style="color:#222222">> </span><span style="color:#6200EE">spawn</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> receivePort = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> receivePort.</span><span style="color:#6200EE">listen</span><span style="color:#222222">(_handleResponsesFromIsolate);</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#0468D7"> Isolate</span><span style="color:#222222">.</span><span style="color:#6200EE">spawn</span><span style="color:#222222">(_startRemoteIsolate, receivePort.sendPort);</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>Also recall that you sent a <code>SendPort</code> back to the main isolate in <a href="#step-3-execute-code-on-the-worker-isolate">step 3</a>. This method handles the receipt of that <code>SendPort</code>, as well as handling future messages (which will be decoded JSON).</p><ul><li>First, check if the message is a <code>SendPort</code>. If so, assign that port to the class's <code>_sendPort</code> property so it can be used to send messages later.</li><li>Next, check if the message is of type <code>Map<String, dynamic></code>, the expected type of decoded JSON. If so, handle that message with your application-specific logic. In this example, the message is printed.</li></ul> <?code-excerpt "lib/basic_ports_example/complete.dart (handle-responses)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">void</span><span style="color:#6200EE"> _handleResponsesFromIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">dynamic</span><span style="color:#222222"> message) {</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (message is </span><span style="color:#0468D7">SendPort</span><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#222222"> _sendPort = message;</span></span> <span class="line"><span style="color:#222222"> _isolateReady.</span><span style="color:#6200EE">complete</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#D43324">else</span><span style="color:#D43324"> if</span><span style="color:#222222"> (message is </span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>) {</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(message);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><div class="header-wrapper"><h4 id="step-5-add-a-completer-to-ensure-your-isolate-is-set-up">Step 5: Add a completer to ensure your isolate is set-up</h4><a class="heading-link" href="#step-5-add-a-completer-to-ensure-your-isolate-is-set-up" aria-label="Link to 'Step 5: Add a completer to ensure your isolate is set-up' section">#</a></div><p>To complete the class, define a public method called <code>parseJson</code>, which is responsible for sending messages to the worker isolate. It also needs to ensure that messages can be sent before the isolate is fully set up. To handle this, use a <a href="https://api.dart.dev/dart-async/Completer-class.html"><code>Completer</code></a>.</p><ul><li>First, add a class-level property called a <code>Completer</code> and name it <code>_isolateReady</code>.</li><li>Next, add a call to <code>complete()</code> on the completer in the <code>_handleResponsesFromIsolate</code> method (created in <a href="#step-4-handle-messages-on-the-main-isolate">step 4</a>) if the message is a <code>SendPort</code>.</li><li>Finally, in the <code>parseJson</code> method, add <code>await _isolateReady.future</code> before adding <code>_sendPort.send</code>. This ensures that no message can be sent to the worker isolate until it is spawned <em>and</em> has sent its <code>SendPort</code> back to the main isolate.</li></ul> <?code-excerpt "lib/basic_ports_example/complete.dart (parse-json)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#D43324">void</span><span style="color:#222222">> </span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#0468D7">String</span><span style="color:#222222"> message) </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#222222"> _isolateReady.future;</span></span> <span class="line"><span style="color:#222222"> _sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">(message);</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><div class="header-wrapper"><h4 id="complete-example">Complete example</h4><a class="heading-link" href="#complete-example" aria-label="Link to 'Complete example' section">#</a></div><details><summary>Expand to see the complete example</summary> <?code-excerpt "lib/basic_ports_example/complete.dart"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">import</span><span style="color:#11796D"> 'dart:async'</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#D43324">import</span><span style="color:#11796D"> 'dart:convert'</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#D43324">import</span><span style="color:#11796D"> 'dart:isolate'</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> worker = </span><span style="color:#0468D7">Worker</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#222222"> worker.</span><span style="color:#6200EE">spawn</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#222222"> worker.</span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#11796D">'{"key":"value"}'</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#222222">}</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324">class</span><span style="color:#0468D7"> Worker</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> late</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> _sendPort;</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> Completer</span><span style="color:#222222"><</span><span style="color:#D43324">void</span><span style="color:#222222">> _isolateReady = </span><span style="color:#0468D7">Completer</span><span style="color:#222222">.</span><span style="color:#D43324">sync</span><span style="color:#222222">();</span></span> <span class="line"></span> <span class="line"><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#D43324">void</span><span style="color:#222222">> </span><span style="color:#6200EE">spawn</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> receivePort = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> receivePort.</span><span style="color:#6200EE">listen</span><span style="color:#222222">(_handleResponsesFromIsolate);</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#0468D7"> Isolate</span><span style="color:#222222">.</span><span style="color:#6200EE">spawn</span><span style="color:#222222">(_startRemoteIsolate, receivePort.sendPort);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> void</span><span style="color:#6200EE"> _handleResponsesFromIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">dynamic</span><span style="color:#222222"> message) {</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (message is </span><span style="color:#0468D7">SendPort</span><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#222222"> _sendPort = message;</span></span> <span class="line"><span style="color:#222222"> _isolateReady.</span><span style="color:#6200EE">complete</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#D43324">else</span><span style="color:#D43324"> if</span><span style="color:#222222"> (message is </span><span style="color:#0468D7">Map</span><span style="color:#222222"><</span><span style="color:#0468D7">String</span><span style="color:#222222">, </span><span style="color:#0468D7">dynamic</span><span style="color:#222222">>) {</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(message);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> static</span><span style="color:#D43324"> void</span><span style="color:#6200EE"> _startRemoteIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> port) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> receivePort = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> port.</span><span style="color:#6200EE">send</span><span style="color:#222222">(receivePort.sendPort);</span></span> <span class="line"></span> <span class="line"><span style="color:#222222"> receivePort.</span><span style="color:#6200EE">listen</span><span style="color:#222222">((</span><span style="color:#0468D7">dynamic</span><span style="color:#222222"> message) </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (message is </span><span style="color:#0468D7">String</span><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> transformed = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(message);</span></span> <span class="line"><span style="color:#222222"> port.</span><span style="color:#6200EE">send</span><span style="color:#222222">(transformed);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#D43324">void</span><span style="color:#222222">> </span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#0468D7">String</span><span style="color:#222222"> message) </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#222222"> _isolateReady.future;</span></span> <span class="line"><span style="color:#222222"> _sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">(message);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div></details><div class="header-wrapper"><h3 id="robust-ports-example">Robust ports example</h3><a class="heading-link" href="#robust-ports-example" aria-label="Link to 'Robust ports example' section">#</a></div><p>The <a href="#basic-ports-example">previous example</a> explained the basic building blocks needed to set up a long-lived isolate with two-way communication. As mentioned, that example lacks some important features, such as error handling, the ability to close the ports when they’re no longer in use, and inconsistencies around message ordering in some situations.</p><p>This example expands on the information in the first example by creating a long-lived worker isolate that has these additional features and more, and follows better design patterns. Although this code has similarities to the first example, it is not an extension of that example.</p><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>This example assumes that you are already familiar with establishing communication between isolates with <code>Isolate.spawn</code> and ports, which was covered in the <a href="#basic-ports-example">previous example</a>.</p></div></aside><div class="header-wrapper"><h4 id="step-1-define-the-worker-class-1">Step 1: Define the worker class</h4><a class="heading-link" href="#step-1-define-the-worker-class-1" aria-label="Link to 'Step 1: Define the worker class' section">#</a></div><p>First, create a class for your background worker isolate. This class contains all the functionality you need to:</p><ul><li>Spawn an isolate.</li><li>Send messages to that isolate.</li><li>Have the isolate decode some JSON.</li><li>Send the decoded JSON back to the main isolate.</li></ul><p>The class exposes three public methods: one that creates the worker isolate, one that handles sending messages to that worker isolate, and one that can shut down the ports when they’re no longer in use.</p> <?code-excerpt "lib/robust_ports_example/start.dart (worker)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">class</span><span style="color:#0468D7"> Worker</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> _commands;</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> _responses;</span></span> <span class="line"></span> <span class="line"><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#0468D7">Object</span><span style="color:#222222">?> </span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#0468D7">String</span><span style="color:#222222"> message) </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Ensure the port is still open.</span></span> <span class="line"><span style="color:#222222"> _commands.</span><span style="color:#6200EE">send</span><span style="color:#222222">(message);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> static</span><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#0468D7">Worker</span><span style="color:#222222">> </span><span style="color:#6200EE">spawn</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Add functionality to create a new Worker object with a</span></span> <span class="line"><span style="color:#6E6E70"> // connection to a spawned isolate.</span></span> <span class="line"><span style="color:#D43324"> throw</span><span style="color:#0468D7"> UnimplementedError</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#0468D7"> Worker</span><span style="color:#222222">._(</span><span style="color:#D43324">this</span><span style="color:#222222">._responses, </span><span style="color:#D43324">this</span><span style="color:#222222">._commands) {</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Initialize main isolate receive port listener.</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> void</span><span style="color:#6200EE"> _handleResponsesFromIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">dynamic</span><span style="color:#222222"> message) {</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Handle messages sent back from the worker isolate.</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> static</span><span style="color:#D43324"> void</span><span style="color:#6200EE"> _handleCommandsToIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222"> rp, </span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> sp) </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Handle messages sent back from the worker isolate.</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> static</span><span style="color:#D43324"> void</span><span style="color:#6200EE"> _startRemoteIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> sp) {</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Initialize worker isolate's ports.</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>In this example, <code>SendPort</code> and <code>ReceivePort</code> instances follow a best practice naming convention, in which they are named in relation to the main isolate. The messages sent through the <code>SendPort</code> from the main isolate to the worker isolate are called <em>commands</em>, and the messages sent back to the main isolate are called <em>responses</em>.</p></div></aside><div class="header-wrapper"><h4 id="step-2-create-a-rawreceiveport-in-the-worker-spawn-method">Step 2: Create a <code>RawReceivePort</code> in the <code>Worker.spawn</code> method</h4><a class="heading-link" href="#step-2-create-a-rawreceiveport-in-the-worker-spawn-method" aria-label="Link to 'Step 2: Create a RawReceivePort in the Worker.spawn method' section">#</a></div><p>Before spawning an isolate, you need to create a <a href="https://api.dart.dev/dart-isolate/RawReceivePort-class.html"><code>RawReceivePort</code></a>, which is a lower-level <code>ReceivePort</code>. Using <code>RawReceivePort</code> is a preferred pattern because it allows you to separate your isolate startup logic from logic that handles message passing on the isolate.</p><p>In the <code>Worker.spawn</code> method:</p><ul><li>First, create the <code>RawReceivePort</code>. This <code>ReceivePort</code> is only responsible for receiving the initial message from the worker isolate, which will be a <code>SendPort</code>.</li><li>Next, create a <code>Completer</code> that will indicate when the isolate is ready to receive messages. When this completes, it will return a record with a <code>ReceivePort</code> and a <code>SendPort</code>.</li><li>Next, define the <code>RawReceivePort.handler</code> property. This property is a <code>Function?</code> that behaves like <code>ReceivePort.listener</code>. The function is called when a message is received by this port.</li><li>Within the handler function, call <code>connection.complete()</code>. This method expects a <a href="/language/records">record</a> with a <code>ReceivePort</code> and a <code>SendPort</code> as an argument. The <code>SendPort</code> is the initial message sent from the worker isolate, which will be assigned in the next step to the class level <code>SendPort</code> named <code>_commands</code>.</li><li>Then, create a new <code>ReceivePort</code> with the <code>ReceivePort.fromRawReceivePort</code> constructor, and pass in the <code>initPort</code>.</li></ul> <?code-excerpt "lib/robust_ports_example/spawn_1.dart (worker-spawn)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">class</span><span style="color:#0468D7"> Worker</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> _commands;</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> _responses;</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> static</span><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#0468D7">Worker</span><span style="color:#222222">> </span><span style="color:#6200EE">spawn</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // Create a receive port and add its initial message handler.</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> initPort = </span><span style="color:#0468D7">RawReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> connection = </span><span style="color:#0468D7">Completer</span><span style="color:#222222"><(</span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">, </span><span style="color:#0468D7">SendPort</span><span style="color:#222222">)>.</span><span style="color:#D43324">sync</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> initPort.handler = (initialMessage) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> commandPort = initialMessage </span><span style="color:#D43324">as</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> connection.</span><span style="color:#6200EE">complete</span><span style="color:#222222">((</span></span> <span class="line"><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222">.</span><span style="color:#6200EE">fromRawReceivePort</span><span style="color:#222222">(initPort),</span></span> <span class="line"><span style="color:#222222"> commandPort,</span></span> <span class="line"><span style="color:#222222"> ));</span></span> <span class="line"><span style="color:#222222"> };</span></span> <span class="line"><span style="color:#6E6E70">// ···</span></span> <span class="line"><span style="color:#222222"> }</span></span></code></pre></div></div><p>By creating a <code>RawReceivePort</code> first, and then a <code>ReceivePort</code>, you’ll be able to add a new callback to <code>ReceivePort.listen</code> later on. Conversely, if you were to create a <code>ReceivePort</code> straight away, you’d only be able to add one <code>listener</code>, because <code>ReceivePort</code> implements <a href="https://api.dart.dev/dart-async/Stream-class.html"><code>Stream</code></a>, rather than <a href="https://api.dart.dev/dart-async/BroadcastStream-class.html"><code>BroadcastStream</code></a>.</p><p>Effectively, this allows you to separate your isolate start-up logic from the logic that handles receiving messages after setting up communication is complete. This benefit will become more obvious as the logic in the other methods grows.</p><div class="header-wrapper"><h4 id="step-3-spawn-a-worker-isolate-with-isolate-spawn">Step 3: Spawn a worker isolate with <code>Isolate.spawn</code></h4><a class="heading-link" href="#step-3-spawn-a-worker-isolate-with-isolate-spawn" aria-label="Link to 'Step 3: Spawn a worker isolate with Isolate.spawn' section">#</a></div><p>This step continues to fill in the <code>Worker.spawn</code> method. You’ll add the code needed to spawn an isolate, and return an instance of <code>Worker</code> from this class. In this example, the call to <code>Isolate.spawn</code> is wrapped in a <a href="/language/error-handling#catch"><code>try</code>/<code>catch</code> block</a>, which ensures that, if the isolate fails to start up, the <code>initPort</code> will be closed, and the <code>Worker</code> object won’t be created.</p><ul><li>First, attempt to spawn a worker isolate in a <code>try</code>/<code>catch</code> block. If spawning a worker isolate fails, close the receive port that was created in the previous step. The method passed to <code>Isolate.spawn</code> will be covered in a later step.</li><li>Next, await the <code>connection.future</code>, and destructure the send port and receive port from the record it returns.</li><li>Finally, return an instance of <code>Worker</code> by calling its private constructor, and passing in the ports from that completer.</li></ul> <?code-excerpt "lib/robust_ports_example/spawn_2.dart (worker-spawn)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">class</span><span style="color:#0468D7"> Worker</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> _commands;</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> _responses;</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> static</span><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#0468D7">Worker</span><span style="color:#222222">> </span><span style="color:#6200EE">spawn</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // Create a receive port and add its initial message handler</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> initPort = </span><span style="color:#0468D7">RawReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> connection = </span><span style="color:#0468D7">Completer</span><span style="color:#222222"><(</span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">, </span><span style="color:#0468D7">SendPort</span><span style="color:#222222">)>.</span><span style="color:#D43324">sync</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> initPort.handler = (initialMessage) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> commandPort = initialMessage </span><span style="color:#D43324">as</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> connection.</span><span style="color:#6200EE">complete</span><span style="color:#222222">((</span></span> <span class="line"><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222">.</span><span style="color:#6200EE">fromRawReceivePort</span><span style="color:#222222">(initPort),</span></span> <span class="line"><span style="color:#222222"> commandPort,</span></span> <span class="line"><span style="color:#222222"> ));</span></span> <span class="line"><span style="color:#222222"> };</span></span> <span class="line"><span style="color:#6E6E70"> // Spawn the isolate.</span></span> <span class="line"><span style="color:#D43324"> try</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#0468D7"> Isolate</span><span style="color:#222222">.</span><span style="color:#6200EE">spawn</span><span style="color:#222222">(_startRemoteIsolate, (initPort.sendPort));</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#D43324">on</span><span style="color:#0468D7"> Object</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#222222"> initPort.</span><span style="color:#6200EE">close</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> rethrow</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> (</span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222"> receivePort, </span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> sendPort) =</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#222222"> connection.future;</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> return</span><span style="color:#0468D7"> Worker</span><span style="color:#222222">._(receivePort, sendPort);</span></span> <span class="line"><span style="color:#222222"> }</span></span></code></pre></div></div><p>Note that in this example (compared to the <a href="#basic-ports-example">previous example</a>), <code>Worker.spawn</code> acts as an asynchronous static constructor for this class and is the only way to create an instance of <code>Worker</code>. This simplifies the API, making the code that creates an instance of <code>Worker</code> cleaner.</p><div class="header-wrapper"><h4 id="step-4-complete-the-isolate-setup-process">Step 4: Complete the isolate setup process</h4><a class="heading-link" href="#step-4-complete-the-isolate-setup-process" aria-label="Link to 'Step 4: Complete the isolate setup process' section">#</a></div><p>In this step, you will complete the basic isolate setup process. This correlates almost entirely to the <a href="#basic-ports-example">previous example</a>, and there are no new concepts. There is a slight change in that the code is broken into more methods, which is a design practice that sets you up for adding more functionality through the remainder of this example. For an in-depth walkthrough of the basic process of setting up an isolate, see the <a href="#basic-ports-example">basic ports example</a>.</p><p>First, create the private constructor that is returned from the <code>Worker.spawn</code> method. In the constructor body, add a listener to the receive port used by the main isolate, and pass an as-yet undefined method to that listener called <code>_handleResponsesFromIsolate</code>.</p> <?code-excerpt "lib/robust_ports_example/step_4.dart (constructor)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">class</span><span style="color:#0468D7"> Worker</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> _commands;</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> _responses;</span></span> <span class="line"><span style="color:#6E6E70">// ···</span></span> <span class="line"><span style="color:#0468D7"> Worker</span><span style="color:#222222">._(</span><span style="color:#D43324">this</span><span style="color:#222222">._responses, </span><span style="color:#D43324">this</span><span style="color:#222222">._commands) {</span></span> <span class="line"><span style="color:#222222"> _responses.</span><span style="color:#6200EE">listen</span><span style="color:#222222">(_handleResponsesFromIsolate);</span></span> <span class="line"><span style="color:#222222"> }</span></span></code></pre></div></div><p>Next, add the code to <code>_startRemoteIsolate</code> that is responsible for initializing the ports on the worker isolate. <a href="#step-3-spawn-a-worker-isolate-with-isolate-spawn">Recall</a> that this method was passed to <code>Isolate.spawn</code> in the <code>Worker.spawn</code> method, and it will be passed the main isolate’s <code>SendPort</code> as an argument.</p><ul><li>Create a new <code>ReceivePort</code>.</li><li>Send that port’s <code>SendPort</code> back to the main isolate.</li><li>Call a new method called <code>_handleCommandsToIsolate</code>, and pass both the new <code>ReceivePort</code> and <code>SendPort</code> from the main isolate as arguments.</li></ul> <?code-excerpt "lib/robust_ports_example/step_4.dart (start-isolate)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">static</span><span style="color:#D43324"> void</span><span style="color:#6200EE"> _startRemoteIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> sendPort) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> receivePort = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">(receivePort.sendPort);</span></span> <span class="line"><span style="color:#6200EE"> _handleCommandsToIsolate</span><span style="color:#222222">(receivePort, sendPort);</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>Next, add the <code>_handleCommandsToIsolate</code> method, which is responsible for receiving messages from the main isolate, decoding json on the worker isolate, and sending the decoded json back as a response.</p><ul><li>First, declare a listener on the worker isolate’s <code>ReceivePort</code>.</li><li>Within the callback added to the listener, attempt to decode the JSON passed from the main isolate within a <a href="/language/error-handling#catch"><code>try</code>/<code>catch</code> block</a>. If decoding is successful, send the decoded JSON back to the main isolate.</li><li>If there is an error, send back a <a href="https://api.dart.dev/dart-isolate/RemoteError-class.html"><code>RemoteError</code></a>.</li></ul> <?code-excerpt "lib/robust_ports_example/step_4.dart (handle-commands)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">static</span><span style="color:#D43324"> void</span><span style="color:#6200EE"> _handleCommandsToIsolate</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> receivePort, </span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> sendPort) {</span></span> <span class="line"><span style="color:#222222"> receivePort.</span><span style="color:#6200EE">listen</span><span style="color:#222222">((message) {</span></span> <span class="line"><span style="color:#D43324"> try</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> jsonData = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(message </span><span style="color:#D43324">as</span><span style="color:#0468D7"> String</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">(jsonData);</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#D43324">catch</span><span style="color:#222222"> (e) {</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">(</span><span style="color:#0468D7">RemoteError</span><span style="color:#222222">(e.</span><span style="color:#6200EE">toString</span><span style="color:#222222">(), </span><span style="color:#11796D">''</span><span style="color:#222222">));</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>Next, add the code for the <code>_handleResponsesFromIsolate</code> method.</p><ul><li>First, check if the message is a <code>RemoteError</code>, in which case you should <code>throw</code> that error.</li><li>Otherwise, print the message. In future steps, you will update this code to return messages rather than print them.</li></ul> <?code-excerpt "lib/robust_ports_example/step_4.dart (handle-response)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">void</span><span style="color:#6200EE"> _handleResponsesFromIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">dynamic</span><span style="color:#222222"> message) {</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (message is </span><span style="color:#0468D7">RemoteError</span><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#D43324"> throw</span><span style="color:#222222"> message;</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#D43324">else</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(message);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>Finally, add the <code>parseJson</code> method, which is a public method that allows outside code to send JSON to the worker isolate to be decoded.</p> <?code-excerpt "lib/robust_ports_example/step_4.dart (parse-json)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#0468D7">Object</span><span style="color:#222222">?> </span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#0468D7">String</span><span style="color:#222222"> message) </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#222222"> _commands.</span><span style="color:#6200EE">send</span><span style="color:#222222">(message);</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>You will update this method in the next step.</p><div class="header-wrapper"><h4 id="step-5-handle-multiple-messages-at-the-same-time">Step 5: Handle multiple messages at the same time</h4><a class="heading-link" href="#step-5-handle-multiple-messages-at-the-same-time" aria-label="Link to 'Step 5: Handle multiple messages at the same time' section">#</a></div><p>Currently, if you rapidly send messages to the worker isolate, the isolate will send the decoded json response in <em>the order that they complete</em>, rather than the order that they’re sent. You have no way to determine which response corresponds to which message.</p><p>In this step, you’ll fix this problem by giving each message an id, and using <code>Completer</code> objects to ensure that when outside code calls <code>parseJson</code> the response that is returned to that caller is the correct response.</p><p>First, add two class-level properties to <code>Worker</code>:</p><ul><li><code>Map<int, Completer<Object?>> _activeRequests</code></li><li><code>int _idCounter</code></li></ul> <?code-excerpt "lib/robust_ports_example/step_5_add_completers.dart (vars)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">class</span><span style="color:#0468D7"> Worker</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> _commands;</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> _responses;</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> Map</span><span style="color:#222222"><</span><span style="color:#0468D7">int</span><span style="color:#222222">, </span><span style="color:#0468D7">Completer</span><span style="color:#222222"><</span><span style="color:#0468D7">Object</span><span style="color:#222222">?>> _activeRequests = {};</span></span> <span class="line"><span style="color:#0468D7"> int</span><span style="color:#222222"> _idCounter = </span><span style="color:#11796D">0</span><span style="color:#222222">;</span></span></code></pre></div></div><p>The <code>_activeRequests</code> map associates a message sent to the worker isolate with a <code>Completer</code>. The keys used in <code>_activeRequests</code> are taken from <code>_idCounter</code>, which will be increased as more messages are sent.</p><p>Next, update the <code>parseJson</code> method to create completers before it sends messages to the worker isolate.</p><ul><li>First create a <code>Completer</code>.</li><li>Next, increment <code>_idCounter</code>, so that each <code>Completer</code> is associated with a unique number.</li><li>Add an entry to the <code>_activeRequests</code> map in which the key is the current number of <code>_idCounter</code>, and the completer is the value.</li><li>Send the message to the worker isolate, along with the id. Because you can only send one value through the <code>SendPort</code>, wrap the id and message in a <a href="/language/records">record</a>.</li><li>Finally, return the completer’s future, which will eventually contain the response from the worker isolate.</li></ul> <?code-excerpt "lib/robust_ports_example/step_5_add_completers.dart (parse-json)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#0468D7">Object</span><span style="color:#222222">?> </span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#0468D7">String</span><span style="color:#222222"> message) </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> completer = </span><span style="color:#0468D7">Completer</span><span style="color:#222222"><</span><span style="color:#0468D7">Object</span><span style="color:#222222">?>.</span><span style="color:#D43324">sync</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> id = _idCounter++;</span></span> <span class="line"><span style="color:#222222"> _activeRequests[id] = completer;</span></span> <span class="line"><span style="color:#222222"> _commands.</span><span style="color:#6200EE">send</span><span style="color:#222222">((id, message));</span></span> <span class="line"><span style="color:#D43324"> return</span><span style="color:#D43324"> await</span><span style="color:#222222"> completer.future;</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>You also need to update <code>_handleResponsesFromIsolate</code> and <code>_handleCommandsToIsolate</code> to handle this system.</p><p>In <code>_handleCommandsToIsolate</code>, you need to account for the <code>message</code> being a record with two values, rather than just the json text. Do so by destructuring the values from <code>message</code>.</p><p>Then, after decoding the json, update the call to <code>sendPort.send</code> to pass both the id and the decoded json back to the main isolate, again using a record.</p> <?code-excerpt "lib/robust_ports_example/step_5_add_completers.dart (handle-commands)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">static</span><span style="color:#D43324"> void</span><span style="color:#6200EE"> _handleCommandsToIsolate</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> receivePort, </span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> sendPort) {</span></span> <span class="line"><span style="color:#222222"> receivePort.</span><span style="color:#6200EE">listen</span><span style="color:#222222">((message) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222"> id, </span><span style="color:#0468D7">String</span><span style="color:#222222"> jsonText) = message </span><span style="color:#D43324">as</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222">, </span><span style="color:#0468D7">String</span><span style="color:#222222">); </span><span style="color:#6E6E70">// New</span></span> <span class="line"><span style="color:#D43324"> try</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> jsonData = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(jsonText);</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">((id, jsonData)); </span><span style="color:#6E6E70">// Updated</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#D43324">catch</span><span style="color:#222222"> (e) {</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">((id, </span><span style="color:#0468D7">RemoteError</span><span style="color:#222222">(e.</span><span style="color:#6200EE">toString</span><span style="color:#222222">(), </span><span style="color:#11796D">''</span><span style="color:#222222">)));</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><p>Finally, update the <code>_handleResponsesFromIsolate</code>.</p><ul><li>First, destructure the id and the response from the message argument again.</li><li>Then, remove the completer that corresponds to this request from the <code>_activeRequests</code> map.</li><li>Lastly, rather than throwing an error or printing the decoded json, complete the completer, passing in the response. When this completes, the response will be returned to the code that called <code>parseJson</code> on the main isolate.</li></ul> <?code-excerpt "lib/robust_ports_example/step_5_add_completers.dart (handle-response)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">void</span><span style="color:#6200EE"> _handleResponsesFromIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">dynamic</span><span style="color:#222222"> message) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222"> id, </span><span style="color:#0468D7">Object</span><span style="color:#222222">? response) = message </span><span style="color:#D43324">as</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222">, </span><span style="color:#0468D7">Object</span><span style="color:#222222">?); </span><span style="color:#6E6E70">// New</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> completer = _activeRequests.</span><span style="color:#6200EE">remove</span><span style="color:#222222">(id)!; </span><span style="color:#6E6E70">// New</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (response is </span><span style="color:#0468D7">RemoteError</span><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#222222"> completer.</span><span style="color:#6200EE">completeError</span><span style="color:#222222">(response); </span><span style="color:#6E6E70">// Updated</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#D43324">else</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#222222"> completer.</span><span style="color:#6200EE">complete</span><span style="color:#222222">(response); </span><span style="color:#6E6E70">// Updated</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><div class="header-wrapper"><h4 id="step-6-add-functionality-to-close-the-ports">Step 6: Add functionality to close the ports</h4><a class="heading-link" href="#step-6-add-functionality-to-close-the-ports" aria-label="Link to 'Step 6: Add functionality to close the ports' section">#</a></div><p>When the isolate is no longer being used by your code, you should close the ports on the main isolate and the worker isolate.</p><ul><li>First, add a class-level boolean that tracks if the ports are closed.</li><li>Then, add the <code>Worker.close</code> method. Within this method:<ul><li>Update <code>_closed</code> to be true.</li><li>Send a final message to the worker isolate. This message is a <code>String</code> that reads “shutdown”, but it could be any object you’d like. You will use it in the next code snippet.</li></ul></li><li>Finally, check if <code>_activeRequests</code> is empty. If it is, close down the main isolate’s <code>ReceivePort</code> named <code>_responses</code>.</li></ul> <?code-excerpt "lib/robust_ports_example/step_6_close_ports.dart (close)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">class</span><span style="color:#0468D7"> Worker</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#0468D7"> bool</span><span style="color:#222222"> _closed = </span><span style="color:#11796D">false</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#6E6E70">// ···</span></span> <span class="line"><span style="color:#D43324"> void</span><span style="color:#6200EE"> close</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (!_closed) {</span></span> <span class="line"><span style="color:#222222"> _closed = </span><span style="color:#11796D">true</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> _commands.</span><span style="color:#6200EE">send</span><span style="color:#222222">(</span><span style="color:#11796D">'shutdown'</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (_activeRequests.isEmpty) _responses.</span><span style="color:#6200EE">close</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(</span><span style="color:#11796D">'--- port closed --- '</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222"> }</span></span></code></pre></div></div><ul><li>Next, you need to handle the “shutdown” message in the worker isolate. Add the following code to the <code>_handleCommandsToIsolate</code> method. This code will check if the message is a <code>String</code> that reads “shutdown”. If it is, it will close the worker isolate’s <code>ReceivePort</code>, and return.</li></ul> <?code-excerpt "lib/robust_ports_example/step_6_close_ports.dart (handle-commands)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">static</span><span style="color:#D43324"> void</span><span style="color:#6200EE"> _handleCommandsToIsolate</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> receivePort,</span></span> <span class="line"><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> sendPort,</span></span> <span class="line"><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#222222"> receivePort.</span><span style="color:#6200EE">listen</span><span style="color:#222222">((message) {</span></span> <span class="line"><span style="color:#6E6E70"> // New if-block.</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (message == </span><span style="color:#11796D">'shutdown'</span><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#222222"> receivePort.</span><span style="color:#6200EE">close</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> return</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222"> id, </span><span style="color:#0468D7">String</span><span style="color:#222222"> jsonText) = message </span><span style="color:#D43324">as</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222">, </span><span style="color:#0468D7">String</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#D43324"> try</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> jsonData = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(jsonText);</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">((id, jsonData));</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#D43324">catch</span><span style="color:#222222"> (e) {</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">((id, </span><span style="color:#0468D7">RemoteError</span><span style="color:#222222">(e.</span><span style="color:#6200EE">toString</span><span style="color:#222222">(), </span><span style="color:#11796D">''</span><span style="color:#222222">)));</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><ul><li>Finally, you should add code to check if the ports are closed before trying to send messages. Add one line in the <code>Worker.parseJson</code> method.</li></ul> <?code-excerpt "lib/robust_ports_example/step_6_close_ports.dart (parse-json)"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#0468D7">Future</span><span style="color:#222222"><</span><span style="color:#0468D7">Object</span><span style="color:#222222">?> </span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#0468D7">String</span><span style="color:#222222"> message) </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (_closed) </span><span style="color:#D43324">throw</span><span style="color:#0468D7"> StateError</span><span style="color:#222222">(</span><span style="color:#11796D">'Closed'</span><span style="color:#222222">); </span><span style="color:#6E6E70">// New</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> completer = </span><span style="color:#0468D7">Completer</span><span style="color:#222222"><</span><span style="color:#0468D7">Object</span><span style="color:#222222">?>.</span><span style="color:#D43324">sync</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> id = _idCounter++;</span></span> <span class="line"><span style="color:#222222"> _activeRequests[id] = completer;</span></span> <span class="line"><span style="color:#222222"> _commands.</span><span style="color:#6200EE">send</span><span style="color:#222222">((id, message));</span></span> <span class="line"><span style="color:#D43324"> return</span><span style="color:#D43324"> await</span><span style="color:#222222"> completer.future;</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div><div class="header-wrapper"><h4 id="complete-example-1">Complete example</h4><a class="heading-link" href="#complete-example-1" aria-label="Link to 'Complete example' section">#</a></div><details><summary>Expand here to see the full example</summary> <?code-excerpt "lib/robust_ports_example/complete.dart"?> <div class="code-block-wrapper language-dart"><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#D43324">import</span><span style="color:#11796D"> 'dart:async'</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#D43324">import</span><span style="color:#11796D"> 'dart:convert'</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#D43324">import</span><span style="color:#11796D"> 'dart:isolate'</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324">void</span><span style="color:#6200EE"> main</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> worker = </span><span style="color:#D43324">await</span><span style="color:#0468D7"> Worker</span><span style="color:#222222">.</span><span style="color:#6200EE">spawn</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(</span><span style="color:#D43324">await</span><span style="color:#222222"> worker.</span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#11796D">'{"key":"value"}'</span><span style="color:#222222">));</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(</span><span style="color:#D43324">await</span><span style="color:#222222"> worker.</span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#11796D">'"banana"'</span><span style="color:#222222">));</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(</span><span style="color:#D43324">await</span><span style="color:#222222"> worker.</span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#11796D">'[true, false, null, 1, "string"]'</span><span style="color:#222222">));</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#0468D7"> Future</span><span style="color:#222222">.</span><span style="color:#6200EE">wait</span><span style="color:#222222">([worker.</span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#11796D">'"yes"'</span><span style="color:#222222">), worker.</span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#11796D">'"no"'</span><span style="color:#222222">)]));</span></span> <span class="line"><span style="color:#222222"> worker.</span><span style="color:#6200EE">close</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222">}</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324">class</span><span style="color:#0468D7"> Worker</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> _commands;</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> _responses;</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#0468D7"> Map</span><span style="color:#222222"><</span><span style="color:#0468D7">int</span><span style="color:#222222">, </span><span style="color:#0468D7">Completer</span><span style="color:#222222"><</span><span style="color:#0468D7">Object</span><span style="color:#222222">?>> _activeRequests = {};</span></span> <span class="line"><span style="color:#0468D7"> int</span><span style="color:#222222"> _idCounter = </span><span style="color:#11796D">0</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#0468D7"> bool</span><span style="color:#222222"> _closed = </span><span style="color:#11796D">false</span><span style="color:#222222">;</span></span> <span class="line"></span> <span class="line"><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#0468D7">Object</span><span style="color:#222222">?> </span><span style="color:#6200EE">parseJson</span><span style="color:#222222">(</span><span style="color:#0468D7">String</span><span style="color:#222222"> message) </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (_closed) </span><span style="color:#D43324">throw</span><span style="color:#0468D7"> StateError</span><span style="color:#222222">(</span><span style="color:#11796D">'Closed'</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> completer = </span><span style="color:#0468D7">Completer</span><span style="color:#222222"><</span><span style="color:#0468D7">Object</span><span style="color:#222222">?>.</span><span style="color:#D43324">sync</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> id = _idCounter++;</span></span> <span class="line"><span style="color:#222222"> _activeRequests[id] = completer;</span></span> <span class="line"><span style="color:#222222"> _commands.</span><span style="color:#6200EE">send</span><span style="color:#222222">((id, message));</span></span> <span class="line"><span style="color:#D43324"> return</span><span style="color:#D43324"> await</span><span style="color:#222222"> completer.future;</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> static</span><span style="color:#0468D7"> Future</span><span style="color:#222222"><</span><span style="color:#0468D7">Worker</span><span style="color:#222222">> </span><span style="color:#6200EE">spawn</span><span style="color:#222222">() </span><span style="color:#D43324">async</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#6E6E70"> // Create a receive port and add its initial message handler</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> initPort = </span><span style="color:#0468D7">RawReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> connection = </span><span style="color:#0468D7">Completer</span><span style="color:#222222"><(</span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">, </span><span style="color:#0468D7">SendPort</span><span style="color:#222222">)>.</span><span style="color:#D43324">sync</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> initPort.handler = (initialMessage) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> commandPort = initialMessage </span><span style="color:#D43324">as</span><span style="color:#0468D7"> SendPort</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> connection.</span><span style="color:#6200EE">complete</span><span style="color:#222222">((</span></span> <span class="line"><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222">.</span><span style="color:#6200EE">fromRawReceivePort</span><span style="color:#222222">(initPort),</span></span> <span class="line"><span style="color:#222222"> commandPort,</span></span> <span class="line"><span style="color:#222222"> ));</span></span> <span class="line"><span style="color:#222222"> };</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // Spawn the isolate.</span></span> <span class="line"><span style="color:#D43324"> try</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#0468D7"> Isolate</span><span style="color:#222222">.</span><span style="color:#6200EE">spawn</span><span style="color:#222222">(_startRemoteIsolate, (initPort.sendPort));</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#D43324">on</span><span style="color:#0468D7"> Object</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#222222"> initPort.</span><span style="color:#6200EE">close</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> rethrow</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> (</span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222"> receivePort, </span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> sendPort) =</span></span> <span class="line"><span style="color:#D43324"> await</span><span style="color:#222222"> connection.future;</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> return</span><span style="color:#0468D7"> Worker</span><span style="color:#222222">._(receivePort, sendPort);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#0468D7"> Worker</span><span style="color:#222222">._(</span><span style="color:#D43324">this</span><span style="color:#222222">._responses, </span><span style="color:#D43324">this</span><span style="color:#222222">._commands) {</span></span> <span class="line"><span style="color:#222222"> _responses.</span><span style="color:#6200EE">listen</span><span style="color:#222222">(_handleResponsesFromIsolate);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> void</span><span style="color:#6200EE"> _handleResponsesFromIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">dynamic</span><span style="color:#222222"> message) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222"> id, </span><span style="color:#0468D7">Object</span><span style="color:#222222">? response) = message </span><span style="color:#D43324">as</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222">, </span><span style="color:#0468D7">Object</span><span style="color:#222222">?);</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> completer = _activeRequests.</span><span style="color:#6200EE">remove</span><span style="color:#222222">(id)!;</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (response is </span><span style="color:#0468D7">RemoteError</span><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#222222"> completer.</span><span style="color:#6200EE">completeError</span><span style="color:#222222">(response);</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#D43324">else</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#222222"> completer.</span><span style="color:#6200EE">complete</span><span style="color:#222222">(response);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (_closed && _activeRequests.isEmpty) _responses.</span><span style="color:#6200EE">close</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> static</span><span style="color:#D43324"> void</span><span style="color:#6200EE"> _handleCommandsToIsolate</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#0468D7"> ReceivePort</span><span style="color:#222222"> receivePort,</span></span> <span class="line"><span style="color:#0468D7"> SendPort</span><span style="color:#222222"> sendPort,</span></span> <span class="line"><span style="color:#222222"> ) {</span></span> <span class="line"><span style="color:#222222"> receivePort.</span><span style="color:#6200EE">listen</span><span style="color:#222222">((message) {</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (message == </span><span style="color:#11796D">'shutdown'</span><span style="color:#222222">) {</span></span> <span class="line"><span style="color:#222222"> receivePort.</span><span style="color:#6200EE">close</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#D43324"> return</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222"> id, </span><span style="color:#0468D7">String</span><span style="color:#222222"> jsonText) = message </span><span style="color:#D43324">as</span><span style="color:#222222"> (</span><span style="color:#0468D7">int</span><span style="color:#222222">, </span><span style="color:#0468D7">String</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#D43324"> try</span><span style="color:#222222"> {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> jsonData = </span><span style="color:#6200EE">jsonDecode</span><span style="color:#222222">(jsonText);</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">((id, jsonData));</span></span> <span class="line"><span style="color:#222222"> } </span><span style="color:#D43324">catch</span><span style="color:#222222"> (e) {</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">((id, </span><span style="color:#0468D7">RemoteError</span><span style="color:#222222">(e.</span><span style="color:#6200EE">toString</span><span style="color:#222222">(), </span><span style="color:#11796D">''</span><span style="color:#222222">)));</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222"> });</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> static</span><span style="color:#D43324"> void</span><span style="color:#6200EE"> _startRemoteIsolate</span><span style="color:#222222">(</span><span style="color:#0468D7">SendPort</span><span style="color:#222222"> sendPort) {</span></span> <span class="line"><span style="color:#D43324"> final</span><span style="color:#222222"> receivePort = </span><span style="color:#0468D7">ReceivePort</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#222222"> sendPort.</span><span style="color:#6200EE">send</span><span style="color:#222222">(receivePort.sendPort);</span></span> <span class="line"><span style="color:#6200EE"> _handleCommandsToIsolate</span><span style="color:#222222">(receivePort, sendPort);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#D43324"> void</span><span style="color:#6200EE"> close</span><span style="color:#222222">() {</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (!_closed) {</span></span> <span class="line"><span style="color:#222222"> _closed = </span><span style="color:#11796D">true</span><span style="color:#222222">;</span></span> <span class="line"><span style="color:#222222"> _commands.</span><span style="color:#6200EE">send</span><span style="color:#222222">(</span><span style="color:#11796D">'shutdown'</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#D43324"> if</span><span style="color:#222222"> (_activeRequests.isEmpty) _responses.</span><span style="color:#6200EE">close</span><span style="color:#222222">();</span></span> <span class="line"><span style="color:#6200EE"> print</span><span style="color:#222222">(</span><span style="color:#11796D">'--- port closed --- '</span><span style="color:#222222">);</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222"> }</span></span> <span class="line"><span style="color:#222222">}</span></span></code></pre></div></div></details><nav id="subnav"><ul><li class="previous"><a href="/language/async">⟨ Asynchronous support</a></li><li class="next"><a href="/null-safety">Sound Null Safety ⟩</a></li></ul></nav><p id="page-github-links"><span>Unless stated otherwise, the documentation on this site reflects Dart 3.5.4. Page last updated on 2024-11-17.</span> <a href="https://github.com/dart-lang/site-www/tree/main/src/content/language/isolates.md" target="_blank" rel="noopener">View source</a> <span>or </span><a href="https://github.com/dart-lang/site-www/issues/new?template=1_page_issue.yml&page-url=https://dart.dev/language/isolates/&page-source=https://github.com/dart-lang/site-www/tree/main/src/content/language/isolates.md" title="Report an issue with this page" target="_blank" rel="noopener">report an issue</a>.</p></div></article></main><footer id="page-footer"><div class="footer-section footer-main"><a href="/" class="brand" title="Dart"><img src="/assets/img/logo/logo-white-text.svg" alt="Dart" width="164"></a><div class="footer-social-links"><a href="https://medium.com/dartlang" target="_blank" rel="noopener" title="Medium blog"><svg><use href="/assets/img/social/medium.svg#medium"></use></svg> </a><a href="https://github.com/dart-lang" target="_blank" rel="noopener" title="GitHub"><svg><use href="/assets/img/social/github.svg#github"></use></svg> </a><a href="https://twitter.com/dart_lang" target="_blank" rel="noopener" title="X (Twitter)"><svg><use href="/assets/img/social/x.svg#x"></use></svg></a></div></div><div class="footer-section footer-tray"><div class="footer-licenses">Except as otherwise noted, this site is licensed under a <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>, and code samples are licensed under the <a href="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</a>.</div><div class="footer-utility-links"><ul><li><a href="/terms" title="Terms of use">Terms</a></li><li><a href="https://policies.google.com/privacy" target="_blank" rel="noopener" title="Privacy policy">Privacy</a></li><li><a href="/security" title="Security philosophy and practices">Security</a></li></ul></div></div></footer></body></html>