【Flutter 专题】92 图解 Dart 单线程实现异步处理之 Isolate (一)

网友投稿 787 2022-05-29

小菜刚尝试了 Future 和 async-await 实现的简单异步操作,但对于耗时较长的异步该如何处理呢?对于 Android 来说可以新开一个线程单独处理,而对应的 Dart 可以用 Isolate 来处理;

Isolate

Isolate 是对 Dart 并发模式的实现,类似于 Android 中的 Thread 线程,但与 Thread 有本质的区别,Thread 可以实现内存共享,而 Isolate 不能;

所有的 Dart Code 都是在 Isolate 中执行的,代码只能使用同一个 Isolate 中的内容,Isolate 有自己的内存和事件循环机制;不同的 Isolate 是内存隔离的,因此只能通过 Port 机制发送消息通信,其原理是向不同的 Isolate 队列中执行写任务;

Isolate 一般通过 spawn / spawnUri 来创建对象;

external static Future spawn( void entryPoint(T message), T message, {bool paused: false, bool errorsAreFatal, SendPort onExit, SendPort onError, @Since("2.3") String debugName});

【Flutter 专题】92 图解 Dart 单线程实现异步处理之 Isolate (一)

简单了解源码,spawn 必须的参数包括需要耗时操作的 entryPoint 和 T 任意类型的 message 数据,即 Isolate 中可以传递任意类型的数据;

_loadIsolateDate() async { await Isolate.spawn(_backgroundWork, ReceivePort().sendPort); } static _backgroundWork(SendPort sendPort) { sendPort.send('BackgroundWork -> currentTime -> ${DateTime.now().millisecondsSinceEpoch}'); }

external static Future spawnUri( Uri uri, List args, var message, {bool paused: false, SendPort onExit, SendPort onError, bool errorsAreFatal, bool checked, Map environment, @Deprecated('The packages/ dir is not supported in Dart 2') Uri packageRoot, Uri packageConfig, bool automaticPackageResolution: false, @Since("2.3") String debugName});

简单了解源码,spawnUri 需要三个必要参数,uri 为其他 Isolate 代码文件的路径;列表 args 为传递的参数列表,message 动态消息,一般是 SendPort;

_loadIsolateDate03() async { ReceivePort receivePort = ReceivePort(); await Isolate.spawnUri(new Uri(path: "./utils/second_isolate.dart"), ['params01, params02, params03'], receivePort.sendPort); receivePort.listen((val) => print('listen -> 【$val】')); }

Isolate 可以方便的利用多核 CPU 来处理耗时操作,因内存不共享,需要通过 Port 进行消息通讯;其中 Port 消息传递也是异步的;

Port 一般是成对出现,分别是 ReceivePort 接收端口和 SendPort 发送端口;而 ReceivePort 也可以生成自己的 SendPort;只需要把 SendPort 传递给其他 Isolate 即可;

_loadIsolateDate01() async { ReceivePort receivePort = ReceivePort(); await Isolate.spawn(_backgroundWork, receivePort.sendPort); receivePort.listen((val) => print('listen -> 【$val】')); } static _backgroundWork(SendPort sendPort) async { sendPort.send( 'BackgroundWork -> currentTime -> ${DateTime.now().millisecondsSinceEpoch}'); Future.delayed(Duration(seconds: 3), () { return sendPort.send( 'BackgroundWork delayed 3s -> currentTime -> ${DateTime.now().millisecondsSinceEpoch}'); }); }

双向通讯与单向通讯一样,把双方的 SendPort 相互传递即可;

_loadIsolateDate02() async { ReceivePort receivePort = ReceivePort(); var sendPort; await Isolate.spawn(_backgroundWork2, receivePort.sendPort); receivePort.listen((val) { if (val is SendPort) { sendPort = val as SendPort; print("双向通讯建立成功"); } print("Isolate Recevie Data -> 【$val】"); if (sendPort != null) { sendPort.send('_loadIsolateDate02 -> currentTime -> ${DateTime.now().millisecondsSinceEpoch}'); } }); } static _backgroundWork2(SendPort sendPort) async { ReceivePort receivePort = new ReceivePort(); receivePort.listen((val) { print("Background Isolate Receive Data -> 【$val]"); }); sendPort.send('BackgroundWork -> currentTime -> ${DateTime.now().millisecondsSinceEpoch}'); sendPort.send(receivePort.sendPort); Future.delayed(Duration(seconds: 2), () { return sendPort.send('BackgroundWork delayed 2s -> currentTime -> ${DateTime.now().millisecondsSinceEpoch}'); }); Future.delayed(Duration(seconds: 5), () { return sendPort.send(receivePort.sendPort); }); }

Isolate 就像机器中的一个小空间,有自己的内存块,因此在使用 Isolate 结束后应及时关闭并销毁当前 Isolate;

isolate.kill(priority: Isolate.immediate);

Tips

小菜刚开始创建 Isolate 时,遇到如下错误;

需要将 Isolate.spawn 中的 message 参数方法设置成 static 方法或放置在 main() 入口;

由于篇幅和测试案例不足,小菜分为两篇小博客对 Isolate 进行学习,对异步的认知还不够深入;如有错误请多多指导!

来源: 阿策小和尚

flutter 任务调度

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:初识物联网初识物联网“The Internetofthings”
下一篇:OpenResty学习地图来啦,速速收藏!
相关文章