做交易网站存在什么风险手机网站怎么导入微信朋友圈
2026/4/15 23:00:51 网站建设 项目流程
做交易网站存在什么风险,手机网站怎么导入微信朋友圈,掘金网站建设,衡阳seo优化推荐概览 本文包含了 Dart 中并发编程工作原理的概念性概述。它从较高层面解释了事件循环、异步语言特性和隔离区。 Dart 中的并发编程既指异步 API#xff08;如 Future 和 Stream#xff09;#xff0c;也指隔离区#xff0c;隔离区允许你将进程转移到独立的核心上。 所有…概览本文包含了 Dart 中并发编程工作原理的概念性概述。它从较高层面解释了事件循环、异步语言特性和隔离区。Dart 中的并发编程既指异步 API如 Future 和 Stream也指隔离区隔离区允许你将进程转移到独立的核心上。所有 Dart 代码都在隔离区中运行从默认的主隔离区开始并且可以选择性地扩展到你显式创建的任何后续隔离区。当你生成一个新的隔离区时它拥有自己独立的内存和自己的事件循环。事件循环是 Dart 中实现异步和并发编程的关键。事件循环Dart 的运行时模型基于事件循环。事件循环负责执行程序代码、收集和处理事件等。当你的应用程序运行时所有事件都会被添加到一个名为事件队列的队列中。事件可以是任何事情从重新绘制用户界面的请求到用户的点击和按键操作再到来自磁盘的输入 / 输出。由于你的应用程序无法预测事件发生的顺序事件循环会按照事件入队的顺序逐个处理它们。感觉和handlelooper机制很像。事件循环的运行方式与这段代码相似while (eventQueue.waitForEvent()) { eventQueue.processNextEvent(); }就是一直等待事件进入事件队列总是取出最新的事件执行。这个示例事件循环是同步的且在单个线程上运行。然而大多数 Dart 应用程序需要同时处理不止一件事情。例如客户端应用程序可能需要执行一个 HTTP 请求同时还要监听用户点击按钮的操作。为了处理这种情况Dart 提供了许多异步 API如 Futures、Streams 和 async-await。这些 API 都是围绕事件循环构建的。下面的例子中发起了一个网络请求使用http库需要导包可能会很慢没有上网工具的话可以配置一下镜像地址。当这段代码进入事件循环时它会立即调用第一个子句 http.get并返回一个 Future 对象。它还会告知事件循环在 then () 子句中的回调函数要一直保留直到 HTTP 请求完成解析。当请求解析完成后事件循环就会执行该回调函数并将请求的结果作为参数传入。Dart 中的事件循环处理所有其他异步事件例如 Stream 对象时通常采用的就是这种相同的模型。Asynchronous programmingFuturesFuture 代表一个异步操作的结果该操作最终会以一个值或一个错误的形式完成。在下面示例代码中Future的返回类型表示一个承诺最终会提供一个 String 值或错误。FutureString _readFileAsync(String filename) { final file File(filename); // .readAsString() returns a Future. // .then() registers a callback to be executed when readAsString resolves. return file.readAsString().then((contents) { return contents.trim(); }); }如果想要获取错误信息只需要和我一样传递第二个参数The async-await syntaxasync 和 await 关键字提供了一种声明式的方式来定义异步函数并使用它们的结果。下面是一个同步代码的示例在等待文件 I/O 时会阻塞const String filename C:\\Users\\Administrator\\Documents\\trae_projects\\dartStuday\\my_dart_project\\bin\\a.txt; void main() { // Read some data. final fileData _readFileSync(); final jsonData jsonDecode(fileData); // Use that data. print(Number of JSON keys: ${jsonData.length}); } String _readFileSync() { final file File(filename); final contents file.readAsStringSync(); return contents.trim(); }下面是类似的代码但做了一些修改已突出显示以使其成为异步代码main () 函数在_readFileAsync () 前使用 await 关键字以便在原生代码文件 I/O执行时让其他 Dart 代码如事件处理程序能够使用 CPU。使用 await 还有一个作用就是将_readFileAsync () 返回的 FutureString转换为 String。因此contents 变量的隐式类型为 String。await 关键字仅在函数体前带有 async 的函数中起作用。如下图所示在 readAsString () 执行非 Dart 代码无论是在 Dart 运行时还是操作系统中时Dart 代码会暂停。一旦 readAsString () 返回一个值Dart 代码的执行就会恢复。StreamsDart 还以流的形式支持异步代码。流会在未来提供值并且会随着时间的推移反复提供。一个承诺会随着时间的推移提供一系列 int 值的对象其类型为 Stream。在下面的示例中使用 Stream.periodic 创建的流每秒重复发送一个新的 int 值。Streamint stream Stream.periodic(const Duration(seconds: 1), (i) i * i); stream.listen((data) { print(data); });下面是periodic函数的注释/// 创建一个以指定[周期]为间隔、持续发送事件的流。////// 事件值由调用[计算方法]生成。该回调函数的入参是一个整数/// 初始值为 0每发送一个事件该值自增 1。await-for and yieldAwait-for 是一种 for 循环它会在提供新值时执行循环的每个后续迭代。换句话说它用于 “遍历” 流。在这个示例中当作为参数提供的流发出新值时函数 sumStream 会发出一个新值。在返回值流的函数中使用 yield 关键字而非 return 关键字。Streamint sumStream(Streamint stream) async* { var sum 0; await for (final value in stream) { yield sum value; } }下面是async*和async的区别Isolates 隔离除了异步 API 之外Dart 还通过隔离区isolates支持并发。大多数现代设备都配备了多核 CPU。为了充分利用多核优势开发者有时会使用并发运行的共享内存线程。然而共享状态的并发容易出错并且可能导致代码变得复杂。与线程不同所有 Dart 代码都在隔离区内部运行。借助隔离区你的 Dart 代码可以同时执行多个独立任务并且在有额外处理器内核可用时会加以利用。隔离区类似于线程或进程但每个隔离区都有自己的内存和一个运行事件循环的单线程。每个隔离区都有自己的全局字段这确保了一个隔离区中的任何状态都无法从其他隔离区访问。隔离区之间只能通过消息传递进行通信。隔离区之间没有共享状态这意味着 Dart 中不会出现像互斥锁、锁以及数据竞争这类并发复杂性问题。话虽如此隔离区也不能完全防止竞态条件。The main isolate 主隔离区在大多数情况下你根本无需考虑隔离区。Dart 程序默认在主隔离区中运行。这是程序开始运行和执行的线程如下图所示即便是单隔离程序也能顺畅运行。在执行下一行代码之前这些应用会使用异步等待async-await来等待异步操作完成。一个运行良好的应用启动迅速能尽快进入事件循环。之后该应用会及时响应每个排队的事件并在必要时使用异步操作。The isolate life cycle如下图所示每个隔离区都从运行一些 Dart 代码开始例如 main () 函数。此 Dart 代码可能会注册一些事件监听器 —— 例如用于响应用户输入或文件 I/O。当隔离区的初始函数返回时如果需要处理事件隔离区会继续存在。处理完事件后隔离区便会退出。Event handling在客户端应用中主隔离区的事件队列可能包含重绘请求以及点击和其他 UI 事件的通知。例如下图展示了一个重绘事件随后是一个点击事件接着是两个重绘事件。事件循环按照先进先出的顺序从队列中获取事件。事件处理在 main () 退出后发生在主隔离区。在下图中main () 退出后主隔离区处理第一个重绘事件。之后主隔离区处理点击事件随后是一个重绘事件。如果同步操作占用过多处理时间应用程序可能会变得无响应。在下图中处理点击的代码耗时过长因此后续事件的处理也会延迟。应用程序可能会出现冻结现象其执行的任何动画也可能会卡顿。在客户端应用中过长的同步操作往往会导致卡顿不流畅的用户界面动画。更糟糕的是用户界面可能会完全失去响应。Background workers如果你的应用程序的用户界面因耗时的计算例如解析大型 JSON 文件而变得无响应可以考虑将该计算任务转移到工作隔离区通常称为后台工作线程。如下图所示一种常见的情况是生成一个简单的工作隔离区由它执行计算然后退出。工作隔离区在退出时会通过消息返回其结果。工作器隔离区可以执行输入 / 输出操作例如读取和写入文件、设置计时器等。它有自己的内存并且不与主隔离区共享任何状态。工作器隔离区可以阻塞而不会影响其他隔离区。Using isolates在 Dart 中使用隔离区有两种方式具体取决于使用场景使用 Isolate.run () 在单独的线程上执行单个计算。使用 Isolate.spawn () 创建一个隔离区它将长期处理多条消息或者作为后台工作程序。在大多数情况下Isolate.run 是推荐用于在后台运行进程的 API。静态的 Isolate.run () 方法需要一个参数一个将在新生成的隔离区上运行的回调函数。int slowFib(int n) n 1 ? 1 : slowFib(n - 1) slowFib(n - 2); // Compute without blocking current isolate. void fib40() async { print(Start fib40 ${DateTime.now()}); var result await Isolate.run(() slowFib(40)); print(Fib(40) $result ${DateTime.now()}); }下面是Isolate.spawn()函数的使用案例import dart:isolate; // 主隔离区 void main() async { print(主隔离区开始ID: ${Isolate.current.hashCode}); // 创建接收端口 final receivePort ReceivePort(); // 创建新隔离区 final isolate await Isolate.spawn( _isolateEntry, // 入口函数 receivePort.sendPort, // 初始消息 ); // 监听子隔离区消息 receivePort.listen((message) { print(收到子隔离区消息: $message); if (message done) { receivePort.close(); isolate.kill(); // 停止隔离区 } }); print(子隔离区已创建ID: ${isolate.hashCode}); } // 子隔离区入口函数必须是顶层或静态函数 void _isolateEntry(SendPort sendPort) { print(子隔离区启动ID: ${Isolate.current.hashCode}); // 向主隔离区发送消息 sendPort.send(Hello from isolate!); // 模拟工作 for (int i 0; i 3; i) { sendPort.send(进度: $i); } sendPort.send(done); }Performance and isolate groups当一个隔离区调用 Isolate.spawn () 时这两个隔离区拥有相同的可执行代码并且处于同一个隔离区组中。隔离区组支持诸如代码共享等性能优化新的隔离区会立即运行该隔离区组所拥有的代码。此外只有当隔离区处于同一个隔离区组时Isolate.exit () 才会生效。在某些特殊情况下你可能需要使用 Isolate.spawnUri ()它会利用指定 URI 处代码的副本来设置新的隔离区。不过spawnUri () 比 spawn () 慢得多而且新的隔离区不在其生成器的隔离组中。另一个性能影响是当隔离区位于不同的组中时消息传递会更慢。Isolate.spawnUri ()主要是用在启动外部的代码副本下面看案例import dart:isolate; import dart:io; void main() async { final receivePort ReceivePort(); // 创建指向外部 Dart 文件的 URI final uri Uri.file(path/to/external_worker.dart); // 使用 spawnUri 创建隔离区 final isolate await Isolate.spawnUri( uri, // 外部文件 URI [], // 参数列表传递给 main 函数 receivePort.sendPort, // 初始消息 ); receivePort.listen((message) { print(外部隔离区消息: $message); }); await Future.delayed(Duration(seconds: 5)); isolate.kill(); // ✅ 可以停止但没有exit优雅 print(隔离区已停止); // 验证是否停止 print(隔离区是否存活); // 实际上没有直接的 isAlive 方法但 kill 后资源会被回收 }// external_worker.dart - 外部文件 import dart:isolate; // 这是 spawnUri 的入口点 void main(ListString args, SendPort sendPort) { // args 来自 spawnUri 的第二个参数 // sendPort 来自 spawnUri 的第三个参数 sendPort.send(来自外部文件的问候); sendPort.send(参数: $args); }Limitations of isolates隔离的局限性隔离区不是线程。如果你是从一种支持多线程的语言转而使用 Dart那么期望隔离区的行为像线程一样是合情合理的但事实并非如此。每个隔离区都有自己的状态这确保了一个隔离区中的任何状态都无法被其他隔离区访问。因此隔离区的能力受到它们对自身内存访问的限制。例如如果你有一个包含全局可变变量的应用程序该变量在你生成的隔离区中会是一个独立的变量。如果你在生成的隔离区中修改了该变量主隔离区中的该变量仍会保持不变。这就是隔离区的预期工作方式在你考虑使用隔离区时记住这一点很重要。消息类型通过 SendPort 发送的消息几乎可以是任何类型的 Dart 对象但也有一些例外情况绑定到特定隔离区的资源Socket、ReceivePort本地交互对象Pointer、DynamicLibrary内存管理对象Finalizer标记为不可发送的自定义类设计启示隔离区通信应该传递数据而不是资源对于需要跨隔离区使用的资源传递配置并在目标隔离区重新创建在设计跨隔离区API时考虑对象的可序列化性隔离区之间的同步阻塞通信能够并行运行的隔离区数量是有限制的。不过这个限制并不会影响 Dart 中隔离区之间通过消息进行的标准异步通信。你可以让数百个隔离区同时运行并推进工作。这些隔离区会以轮询的方式在 CPU 上进行调度并且经常相互让出执行权。在纯 Dart 之外隔离区只能通过 FFI 调用 C 代码来进行同步通信。如果隔离区的数量超过限制在 FFI 调用中通过同步阻塞来尝试隔离区之间的同步通信可能会导致死锁除非采取特殊的处理措施。该限制并非硬编码为某个特定数字而是根据 Dart 应用程序可用的 Dart 虚拟机堆大小计算得出的。为避免这种情况执行同步阻塞的 C 代码需要在执行阻塞操作前离开当前的隔离区并在从 FFI 调用返回 Dart 之前重新进入该隔离区隔离区在web所有 Dart 应用都可以使用 async-await、Future 和 Stream 来进行非阻塞、交错的计算。不过Dart Web 平台不支持隔离区。Dart Web 应用可以使用 Web Worker 在后台线程中运行脚本这与隔离区类似。但 Web Worker 的功能和性能与隔离区存在一定差异。例如当 Web Worker 在线程之间发送数据时它们会来回复制数据。不过数据复制可能会非常缓慢尤其是对于大型消息而言。隔离区Isolates也会做同样的事情但还提供了一些 API这些 API 能够更高效地传输存储消息的内存。创建 Web Worker 和隔离区Isolate的方式也有所不同。你只能通过声明一个单独的程序入口点并对其进行单独编译来创建 Web Worker。启动 Web Worker 类似于使用 Isolate.spawnUri 来启动隔离区。你也可以使用 Isolate.spawn 来启动隔离区这种方式需要的资源更少因为它会复用一些与生成它的隔离区相同的代码和数据。而 Web Worker 没有与之等效的 API。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询