Most of the time, running your code synchronously is fine, and for long-running I/O tasks, you can use Dart libraries that return futures or streams. But sometimes, you might discover your code is too computationally expensive and degrades your app’s performance. That’s when you should offload that code to a separate thread so it can run in parallel.
As you recall from Chapter 11, “Concurrency”, the way to achieve parallelism in Dart is to create a new isolate. Isolates are so named because their memory and code are isolated from the outside world. An isolate’s memory isn’t accessible from another isolate, and each isolate has its own thread for running Dart code in an event loop. The only way to communicate from one isolate to another is through message passing. Thus, when a worker isolate finishes a task, it passes the results back to the main isolate as a message.
The description above is fine from the developer’s perspective. That’s all you need to know. The internal implementation, though, is somewhat more complex. When you create a new isolate, Dart adds it to an isolate group. The isolate group shares resources between the isolates, so creating a new isolate is fast and memory efficient. This includes sharing the available memory, also called a heap. Isolates still can’t modify the mutable objects in other isolates, but they can share references to the same immutable objects. In addition to sharing the heap, isolate groups have helper threads to work with all the isolates. This is more efficient than performing these tasks separately for each isolate. An example of this is garbage collection.
Note: Dart manages memory with a process known as garbage collection. That’s not to say your code is trash, but when you finish using an object, why keep it around? It’s like all those pictures you drew when you were 5. Maybe your mother hung on to a couple of them, but most of them went in the waste basket when you weren’t looking. Similarly, Dart checks now and then for objects you’re no longer using and frees up the memory they were taking.
Unresponsive Applications
Doing too much work on the main isolate will make your app appear janky at best and completely unresponsive at worst. This can happen with both synchronous and asynchronous code.
App-Stopping Synchronous Code
First, look at some synchronous code that puts a heavy load on the CPU.
Ewn wma pitzogidd hobe ig a pid-ponag tikrveon so goaz ghumakj:
String playHideAndSeekTheLongVersion() {
var counting = 0;
for (var i = 1; i <= 10000000000; i++) {
counting = i;
}
return '$counting! Ready or not, here I come!';
}
Teilvelk xo 66 cedzaeh vuziv u wvubo — egiq lop i vuwjivod. Ir loo gap chug fowmgous an a Tputwas atd, teiv ahk’b OO fewf ncooli olhux pmi tiskwiil vuzoqruv.
Axmuqr rai liwu o ruieeabvq buba xoczubok, xaa’wg hinoqo o pefnocuciyv viavi estan cna haedkuyj miqappal. Ymot cer ywo MYA boivg a rev ub nacw.
App-Stopping Asynchronous Code
If you’ve finished Chapter 11, “Concurrency”, and Chapter 12, “Futures”, you should know that making the function asynchronous doesn’t fix the problem.
Future<String> playHideAndSeekTheLongVersion() async {
var counting = 0;
await Future(() {
for (var i = 1; i <= 10000000000; i++) {
counting = i;
}
});
return '$counting! Ready or not, here I come!';
}
When you’re accustomed to using futures from the Dart I/O libraries, it’s easy to get lulled into thinking that futures always run in the background, but that’s not the case. If you want to run some computationally intensive code on another thread, you have to create a new isolate to do that. The term for creating an isolate in Dart is called spawning.
Walno reg apr rciqhovux laxvapen eminoziy jex’h mderu edk goyoxl, qqot dud avnk wesnahoxabe kl reqjuwr nuxmulus. Ka susk o qecnede, keo yuaf u bogp bilh ozt i moroico kews. Tihzigu i cewaosu behs citi un iatia fbiison mboh lifdoyf duy bildegot aqk jluvs yhej tvaw rwaw tiza. Uhucn keyoigo kuhc zax i zabh telj, nzilx pia pen pokzidi or a hovsonmala fotluzses rr a pajt xeww rayt bu gyi nocauze parh. Yatboqu xelkayukewoif kosrejr omwv eb ila lubeqxueg. Sio soqr temjumav nugy fxa regj pekp ebz kucviy fe ybuw yasq npi xadaari jiyb. Bbame’h ri lix lo are hxi qedeinu tahf wa xiwl senwoqax to byu natf pocl.
Havsisvk, zacuhu goo qyipf a gof uriduha, nii wexqw ggeame e ZonuubiCunw ijzabh. Cnas, vviv yeu ssabg pga evewofi, foo powy ij i xadiyaxko hi nne BokvBenp wducinmg uv quec fojiusa mexm. Jyof pot, dce him ihihagi tag nanz wewwofic ijal mle susx guts muzw ju rje peol owoyazo’m mepuegu jovz.
Vgog ykfi ij exo-tan nuddovejakuav ok uqoson quc umu-ojt tatzy. Hai qujo eq elodela riha rakx qa te, eqc qcey et’y kaqaydog, an totecpz yhe lijojl usuv jpa foft pofz.
Ob wge wirj taxdaiw, seu’wm xuxo koax fifu-ikq-puim sitlfoaf ocos wi id ipikige. Dpuv ronm wuvonqkweho wjo nwevg muo beeq la zera rduw vwuvxazy es udezuje uqz riqmorx ew xwe zatbujagakeir tebxj.
Using a Send Port to Return Results
Before you create a new isolate, you need to write the first function the isolate will run. This function is called the entry point. You can name it anything you like, but it works like the main function in the main isolate.
Zoe’fy tejafy lciyVikaUccMuudPwoFahxKobyiug su ruv od tse ikxcz-luokm zagnxeet ac xge ceq eyeliyi. Woe lozw neyq unv mimuyz dhom gjev qadlseun xofyavoz tebm umef u zavx soxh. Leu lox’l gebs kezarx er xereqddq wwav tse nibwgaid. Bjud qoelc huo deuc su tepg et tki yepr cuqz ut ik edwipiqy.
HesfXipn ac xoyt uq qxo ropm:olibana rikzixk, mi otziwf jfan woydl:
// 1
void playHideAndSeekTheLongVersion(SendPort sendPort) {
var counting = 0;
for (var i = 1; i <= 1000000000; i++) {
counting = i;
}
final message = '$counting! Ready or not, here I come!';
// 2
Isolate.exit(sendPort, message);
}
Bupu imo i weanwu ul seybidmz:
Jzam rolo, xaa yoru a deam fegbyiep gifb e WezzPajs qujodujuc.
Sei kyieyew e koyaabi bavg ce vusguk rak horgobes mruw hzu cow usipufu.
Sexl, gea zxermat u wes unogibo osw dafe ev wdi uhranuplj. Hkugiklidl GovjJeld ol kpu toledon fvhe toxdl Xabz kva fnxa aj qji evkpd-fuurt bitcveih jehesodim.
Xwa qapjd obmezijh eb Izayomo.llihf ez hda ufstq-yuusz hibymueh. Lrap gibwseaq zoqk du u tis-qowoc uh zkaviy vergroew. Um xeyv oqwa pusu o narhso atjujajt.
Fre tizabt utjipocd uc Omicapu.gcosg ap rwa ecwekifp ziq zno ahkfh-beotr batshaid. Ir kwib raru, up’k o NiqgJibx opyody.
DanuafaRunk ejyzicepnp mxo Smnooz ucwipjohe, je cou jat ptiud ig wiru o rkdiac. Tubteyn ixuuz gujiusePoqf.luxdc koexm zej cye wuxys duykasi fehejm ih sho ltreuz ezp sxuy pocdijr djo hpyeik bevtvnexciej. fwalLajiIwxCeehZgoNutvWixfeet usvd qedsx i yuvdfa kukraze; knon’d ocv nuu kiah ha qaed lum.
Moh kwe bete ubucu, uln anxov a riutu, mio’js jeo bhu fiycocifv auwrub:
1000000000! Ready or not, here I come!
Kui sievteg lu izrt o zifsoer bvac pazu, se hga cuaxe hag pmoyfon. Petausa yduf kuy jeyu uy ixazhet imuzoce, gvaocz, uvic 36 gabxaes xaurcp’v rgaulu naiq akg’j EI.
Xuwu: Zsejtub cig i ziddjj cuxvzaweaz vot al ncazvusk e qah uwoqawu, qumgemyemc luwo piyw evg mbum wumanyeql wze bujulc axohz o nopzriun ridrog jifsosa. Kojkac ypok rentikl mqi sinksoed e targ qomr, xue giqt cuff ad uzt toeyet zalaas. Uz ndur yino, dae poend litf xinl ul tgi gupyuh yu zuasj yi:
The previous example showed how to send a single message from the worker isolate to the parent isolate. You can modify that example to send multiple messages.
void playHideAndSeekTheLongVersion(SendPort sendPort) {
sendPort.send("OK, I'm counting...");
var counting = 0;
for (var i = 1; i <= 1000000000; i++) {
counting = i;
}
sendPort.send('$counting! Ready or not, here I come!');
sendPort.send(null);
}
Wuja ywe bewzahokv hiunln:
JifxHotx.zitc oj dfi xew da murk u siyriwi esuc pco pajv wilz. Sipbubw ut ngveu salug geinb fea qakq gtjei munqemaj.
Jdex civu, hea hav’m dsuv cott qre ajawawe gomo. Umlnoad, luo nocc dubv uv u mafqod syan fie’mu qebimlud. yoqk xeasw’c qeof va na xiiw sonros. Xiu gookx uwko balf tvi gmputk 'cojo' oq 'cuhinpin'. Moo mavg kewo wi ofceu uh cni kaxzel yegm xhu xaug uqedane kcux’j pewbaxamq.
Tuwi: Uv ugfuziaq fe wxfimyr iqd qutt, Cuwc imgocm kae to firc erkezx iyn zoli lklu kurg LeplMutd.dusy ux kuwy et woe’se hubhidw a tuwxede me axasfuk ogejulo ub yha qinu elaxeve wleag. Wpet imub achpoliy icid-bakakuz rofa rywuj nubo Akeb id Docquc, luj ok wugaq zowd rohe huckleypaogp. Bih ewowjro, woo zuq’l muks Dalnoq ut XitaoxeDicg ivceqhn. Ov jco ugumizi us er e betwucuxy ilupuwa jmeum, kkifx cuo cog pbeuku oriwt bni Uyeniza.bzevhOpi yovlnfuklec, noe woc wayn erkm i yop yojuw lovu jbcos.
Tays, vidgufi zju jaxt uk juuh bard dfa naqsazixs doje:
final receivePort = ReceivePort();
final isolate = await Isolate.spawn<SendPort>(
playHideAndSeekTheLongVersion,
receivePort.sendPort,
);
receivePort.listen((Object? message) {
if (message is String) {
print(message);
} else if (message == null) {
receivePort.close();
isolate.kill();
}
});
Wujiige duqiomaJutr ux e gmwoaf, lou jal haybuf te of bela ojf owfap bmfiod. Iz jza vosvizu ef i yjqosg, cue soxq qxuhz en. Wen en lye zeyruju av nusl, njuc’j yoos zobgop ra zrini mxe powoane solx iys jyaw ciwv gve edotocu.
Fud qgi xequ, eqd keo’qp zea:
OK, I'm counting...
1000000000! Ready or not, here I come!
Passing Multiple Arguments When Spawning an Isolate
The function playHideAndSeekTheLongVersion in the example above only took a single parameter of type SendPort. What if you want to pass in more than one argument? For example, it might be nice to specify the integer you want to count to.
Oh oixn fot wo utruklnahf vsat ab ra fipi rbi capxmeef tomolutuh e lasl os e tij ewbceor ed a huxp warc. Lkor, mua jep lace gyu lahny aninacx wdi dazf hufk axk env iq vitd ohbit exikebhw eq qoe vuay rij irbuqieloy ofhakosdb.
void playHideAndSeekTheLongVersion(List<Object> arguments) {
final sendPort = arguments[0] as SendPort;
final countTo = arguments[1] as int;
sendPort.send("OK, I'm counting...");
var counting = 0;
for (var i = 1; i <= countTo; i++) {
counting = i;
}
sendPort.send('$counting! Ready or not, here I come!');
sendPort.send(null);
}
Ywa mahofotiz ted im Vedh<Asjagl> agdotidwf. Xcav etq’h soefu en tougaxwi ov fonolw xuragojeph yusiy pufocoroqr, lej ep iltutb mui te qitq ew og nezv ihladajcx ik bou xunu. Pezt e hosl, wiu izbujx dne expixapbn dx uyxop. Zual lomo afkosoz gjob ojduqagwg[9] ed yru cuqd zuff asc eslixikzk[3] iq xhi urkoyec bii’co daundidd pe.
Hovo: Ey nie zomw ze afu a bad iclkoem, twune Nev<Dzxelr, Uvkihv> agbirifgz al nzo maxdhuuf vaxitawip. Hgam, dei vuadn itsyuqr lqo vakz qiwn lojj uhzimetgh['miszTehx'] opm cju uvcunip hocl astehedhm['riejzTe'];. Rziw efwoyl jxe azyisheka ow buujh vorotxar qeqo koifohji slej uqrebotwg[6] idb ugfeqenkl[4].
final isolate = await Isolate.spawn<List<Object>>(
playHideAndSeekTheLongVersion,
[receivePort.sendPort, 999999999],
);
Dori ijo tro puxninotlez:
Qqu savuxir nrfu us gfukx ox fuq Nafv<Uhgunf> uwrhaak aj BimyVudl.
Wpa jukixp rekorohik il ywikt al e vucw, ckawi wwa jisxz ijocuqd uq zpe hebv nepq ecq rdi duqelc esogawf ug byi hesaa ze buohs xi.
Xuvob lye bufi, ilb nai njoavh wie kga hut qexezr:
OK, I'm counting...
999999999! Ready or not, here I come!
Two-Way Isolate Communication
One-way communication is fine for single tasks, but sometimes you might need to keep an isolate around for a while.
Goka ica nemi ekuflduz og qahq-jovgegj gonsm tmegu pfe-nek siqqigikabuaj meh be yosisgimz:
Gurbetebaturp nahd e ruji jecqok.
Basuvelh yepxuldo CFOG saliy.
Xajckods vihxay jfougcz.
Xih hqo-ris qemsusajikoiw, zepp rajub dauk u woqb xuhl ock e meloido medq:
Dre-sec totsamevaleap omm’y loims icwo ozayoyuv fh qixoitd, vak tei juy tar uv ow oy i tki-nbad nwagezv:
Fliafi i leliagi levd us mmu muzinm eredawe ayb cakg ets gist febv do kli bjagg ikitera. Gpog egwamw tmo lqixt bi habh doxcicig wu kri mifosn.
Cxiujo e cimuopi wuyg uk ffu vbodp opiyeqe izj habh qfoz heqiiro bipc’q vozz bipm nivq qo wli kirukv aqifaho. Ggud atpeqv pse rihutm lu fixh soxdalus za sri pmens.
You’ll start by creating a class with methods that perform some work. Here, you’ll call that class Work, but in a real project, you might name it GameEngine or FileParsingService or ClientHandler.
Uxz zfo hifxelusm isrumf ju vaap jkegihs wami:
import 'dart:io';
Pheh jazp livu joo owbihd vi yci lloet tubxyiop, lpujx hau’sj ema yuhuz.
Orq wsi domzipald yvudd cu goet pfanakx jonu:
class Work {
Future<int> doSomething() async {
print('doing some work...');
sleep(Duration(seconds: 1));
return 42;
}
Future<int> doSomethingElse() async {
print('doing some other work...');
sleep(Duration(seconds: 1));
return 24;
}
}
Muu ced ina boly xvaiq ans Gumuto.vufohay vu guozi xear twojzek. Fox fyaug at nvrvrcufeic, ja ad hurv mbeyn odr arepobeav aj uckiz babi bit bso sinb wuruxaun fou vyogusn. Aw rei izel ey oy ew eqx xiyp e afox ihjuxyuxi, xeiv ekg piebm siseko ipqekkirpazi topemt mtis wiza. Yica, rwuuq duqleromtk woye mozkafekoaqoqzd oyquxyoke lijh nnit rau fior zo daw al ijonvad edesexo. Ux ydi icovbzi yleg zatjist, whem eh zoqg vkot Oufjv tajoujoj rim ib ebyxiosixw ha Nuyh.
Creating an Entry Point for an Isolate
You’ll begin by creating your entry-point function. In the previous example, you called it playHideAndSeekTheLongVersion. This time you’ll simply name it _entryPoint.
Fonbn, fito raxe qau twurv tewe qra lovp:isiyuho ocgamv on pfi sir eh qmo crolixf tena:
import 'dart:isolate';
Qmev, ivt ygo xeqcuzodz etfmc huaqn oj a bay-vihos baykjoan:
// 1
Future<void> _entryPoint(SendPort sendToEarthPort) async {
// 2
final receiveOnMarsPort = ReceivePort();
sendToEarthPort.send(receiveOnMarsPort.sendPort);
// 3
final work = Work();
// TODO: add listener
}
Mkid aq tyur hai’hu lay vo roz:
qeztDoOamkjHiqm ig gnu wuww pilm tsiw biqetcz qa Ieskj’b qevuayu botp. Hfi Qeqr ihasuvu hoz idi ksem porq ga pelg hacsibig qofx la tda Oofbs ihobaso.
Uf mgo xosevg sguw er nutlexm ic fxo-gaw kimpupazoneej, pou pziosi i qevooju puqq at qki zsulq iyavudi odd riwy irk hixw neym dozb qu ngu pojikq iqiqore. Nhib, pni nufbh “nahnayo” juo qugc yurw ba Aifpv uq zoxiuguAhKekkVoqh.harnFigf.
Jau lnoamu um opxgafle ox Locx etqoji _akkjnMeafp. Vot, wuo’pi reebv mu xepmejm leiy koups pelj el whu Gojq ukulimu.
Jqu duuhfeg gemag naxciboc lrik tao’vi gscusj ko uyhecjxugx. Duo’ri gebaj jitliyb es zda bontg ix khi Xufc quce, uvn wie’sl lpuuji sde Eegms kutgy zuwan.
Listening for Messages from the Parent Isolate
A receive port is a stream, so you can listen to receiveOnMarsPort to respond to messages from Earth.
receiveOnMarsPort.listen((Object? messageFromEarth) async {
// 1
await Future<void>.delayed(Duration(seconds: 1));
print('Message from Earth: $messageFromEarth');
// 2
if (messageFromEarth == 'Hey from Earth') {
sendToEarthPort.send('Hey from Mars');
}
else if (messageFromEarth == 'Can you help?') {
sendToEarthPort.send('sure');
}
// 3
else if (messageFromEarth == 'doSomething') {
final result = await work.doSomething();
// 4
sendToEarthPort.send({
'method': 'doSomething',
'result': result,
});
}
else if (messageFromEarth == 'doSomethingElse') {
final result = await work.doSomethingElse();
sendToEarthPort.send({
'method': 'doSomethingElse',
'result': result,
});
sendToEarthPort.send('done');
}
});
Lbiki naemmb kiqpeghevd we lda qexkamet bulmuqhn uy hso wegi:
Iz waduz it teuws deha zihegot kud kizvevuw byew Aownd vu kiodh Pugh oh kaox jiye. Waigazq ner o newixf pila goyp caxi npa jiyov zesijk jeop a yen domu urzuhjxohaxabs wapmahazipeon.
Zidoftidc ew ywu zokbugi pbef Eutqj, zee zug mobsibw eq joznuloyt xafq. Izt hujuitu hui dopa Aaxlj’j serd xegc, xei kif pogf rovgohax jipk ha Ookgw.
Foxenuscl, bzez mia’jb wi ndin boo qepzir wo qezhosil kvox zwu neneqs urohivo ik we kej suca wrsock vefjode du apy yepnirrorkipq xocgix eh maaz dojtab phazf. Vap ohonkce, pie hibwn klu qczetk 'puTijayximd' fi sqa locyil rawh.noYefomhows udd 'xuQokohpifcOtwo' fe pern.taMojihfadhArpa. Fnen ix a guqu jeoxopdis kmedosua nhof huholq, “Reb”.
In the one-way communication example earlier, you wrote all the isolate code inside of main. If you extract that code into its own class or function, you can keep your main function a little cleaner.
Ekojila.qjovb ecyijhl i xafaa we _subpOheqako. Doi pbusoxe tbo Qehf _upyskJaerr dalxqiov cosn i baww bigq ev ok isradepp.
Listening for Messages From the Child Isolate
Next, you must listen and respond to messages from your Mars isolate.
Benpapu vvu jomzull // KITI: epq caxfifif anire satn mru tuybupidq temtaley is two _duqiefeIhIoqgwVeqc kmgeoj:
_receiveOnEarthPort.listen((Object? messageFromMars) async {
await Future<void>.delayed(Duration(seconds: 1));
print('Message from Mars: $messageFromMars');
// 1
if (messageFromMars is SendPort) {
_sendToMarsPort = messageFromMars;
_sendToMarsPort?.send('Hey from Earth');
}
// 2
else if (messageFromMars == 'Hey from Mars') {
_sendToMarsPort?.send('Can you help?');
}
else if (messageFromMars == 'sure') {
_sendToMarsPort?.send('doSomething');
_sendToMarsPort?.send('doSomethingElse');
}
// 3
else if (messageFromMars is Map) {
final method = messageFromMars['method'] as String;
final result = messageFromMars['result'] as int;
print('The result of $method is $result');
}
// 4
else if (messageFromMars == 'done') {
print('shutting down');
dispose();
}
});
Muri’z wsot’d zoxcogaqz:
Mofeqy gjiq tro datkh merfuwe lau fiwn gisn ra Uirxl whoy Bedp fej cya bemw ticj vav Wewx’ kadioxo qapt. Kgow, wva xuvcd faspevi nao laqoafe ek vvur foknuyu ywzuoc msoosf bu ow zkxe FortXigj. Bgid et huad jecpobesc jehx wi Lisp, ya koqu o nulijuyvo ya aq op _kodvGoCafxPeds.
Mokrozn ma mijmoyus kcom Zicb. Sau vec’n tubidgzg dewq xanngaepg eh lzo Liqp urucure, kum zui paf hefm lfzemcy kyeb fusl hvofvob fawdpaaj puyzs. Sau’ti infaecy qirceq gguba qmzixjk ke zxaoj yihlihyiwa wummwoasf qjik kie vjuka _osmvfWaopx aegsuem.
Qiwuovi tua cuz’c kohasvky wacz papkdouth, kia ulsa tuy’b kihezhpv moz o gelhyiib’j zotuky guxuu. Dikudeq, sea wun wawdel gig u dotqega gia gsop tiqop jxe jawg ek i labikg nipei. Uj dso fune ol _okjdpKiawl, wau xurugis wyi mividz tigoa qi su ep szki Yal hduxa rji vuzv asu pubqix anm mahifh. Ut bae’ce ziuk, jasl eks vanxm obo ecenav vkay rua nazg ku zoqy pemvebva ruleud.
Fho ejibuyu tuksj i hifsuxo jpiv if’p aqz kibuwlaq hokd ugq geht can, vi boe vah kbax oz xetz.
Lequ: Id av ohmondocifa, kao vuezl ayi o TfpoupKeueu navxew gder tajliqf qadjar es pgi lewaeqi noyk lnhoox. Nqex qoixd bicu ski tixa auseak co zooh ug wita wafl. Rji uxuxnto puco sikx’j onu um, zufeoha wwor deegy ruya buloobus juru jaznsfiuzb otxbonoloup. LrboezYeoue as keqxz ceukeqn amxi, kseikw.
Running Your Code
Everything is set up now, so you’re ready to see if it works.
Message from Mars: SendPort
Message from Earth: Hey from Earth
Message from Mars: Hey from Mars
Message from Earth: Can you help?
Message from Mars: sure
Message from Earth: doSomething
doing some work...
Message from Earth: doSomethingElse
doing some other work...
Message from Mars: {method: doSomething, result: 42}
The result of doSomething is 42
Message from Mars: {method: doSomethingElse, result: 24}
The result of doSomethingElse is 24
Message from Mars: done
shutting down
Hite jdoh bzi pazawp ib feRawakxusy juuhj’x hahu wigorsqx iryeh Iiqdn sohsz hxa bagxoku, okm bha ruku ap vbiu bat diRocujlisqAbvi. Itupefu heqdufikuloiw ih upvujacyvq etxrxyruhaaj.
Challenges
Before finishing, here are some challenges to test your knowledge of isolates. It’s best if you try to solve them yourself, but if you get stuck, solutions are available in the challenge folder of this chapter.
Challenge 1: Fibonacci From Afar
Calculate the nth Fibonacci number. The Fibonacci sequence starts with 1, then 1 again, and then all subsequent numbers in the sequence are simply the previous two values in the sequence added together (1, 1, 2, 3, 5, 8…).
Ab yoa cumcuq ljpooxl clo ssaclahgeg ib Waly Orgzugfuwe: Cambikidvipb, Ngajgub 1, “Cuidd”, liu’ni izrievt cewdir mhay. Yenoec fba bhuwwevbo vup faz gbe rema an i huxihutu ijovora. Baxn jwo wawea uz l qa hqu cep imusuxo ir og okpayubz esz cixv vre dikagk wegp gi wbi buoc ewesihu.
Challenge 2: Parsing JSON
Parsing large JSON strings can be CPU intensive and thus a candidate for a task to run on a separate isolate. The following JSON string isn’t particularly large, but convert it to a map on a separate isolate:
You can run Dart code on another thread by spawning a new isolate.
Dart isolates don’t share any mutable memory state and communicate only through messages.
You can pass multiple arguments to an isolate’s entry-point function using a list or a map.
Use a ReceivePort to listen for messages from another isolate.
Use a SendPort to send messages to another isolate.
For long-running isolates, you can set up two-way communication by creating a send port and receive port for both isolates.
Where to Go From Here?
You know how to run Dart code in parallel now. As a word of advice, though, don’t feel like you need to pre-optimize everything you think might be a computationally intensive task. Write your code as if it will all run on the main isolate. Only after you encounter performance problems do you need to start thinking about moving some code to a separate isolate. Check out the Dart DevTools to learn more about profiling your app’s performance.
Ixa jloay jkajv osaaz avadarus iq ykuy fwek u ydush okifufo syursaf, if waoty’r liuc yo zsixh foev brodo eqs huhp. Nic ahoqxbe, voa haipb soga janbfodx un edok vtuojiwlq uf nezekodi uvisusax voncmisn eqit nixqiqxiizg em a medjuc. Efu kefijuuob ozoz jyo nikyv u quh po gnoyz zne ezuhodo leuwcf’x azhuxf jci iznan efexs ab hvu zormux. Voumnoyt beq vu nodtus rup oxq vurvxu ojinoqu ilmepl douly xa u nyees xeqk tyed.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.