我在 Flutter/Dart 异步代码执行方面遇到问题,例如它是如何工作的

2024-02-24

在 Flutter 中,我们使用 async wait 和 Future,有人可以解释一下,如果我们不使用另一个线程(在 dart 中不能这样做)并仅在主 UIThread 上运行作业,应用程序不会变得不稳定,因为即使我们等待作业执行它最终只会在 UIThread 上执行。 我也在某处读到过有关分离株的信息。但无法描绘出准确的画面。如果有人可以详细解释一下。


我认为您在谈到 Dart 中的异步方法时错过了一些东西。 Dart 是单线程编程语言,Java 或 C# 是多线程编程语言,忘记了async作为一个新线程,它不会发生在 Dart 中。

通常,您在 Dart 中所做的一切都将从 UI-Thread 开始。 在 Flutter 中,主 UI 线程用于渲染界面并响应用户输入。在此线程上运行繁重的计算或长时间运行的任务可能会导致应用程序体验不稳定,因为 UI 会被阻塞。为了解决这个问题,Dart 提供了异步编程功能,例如 async/await、Future 和 Isolates。

Async/await 是 Dart 中的构造,允许您编写非阻塞代码。当您将函数标记为异步时,表示该函数可以运行异步操作。在异步函数内,您可以在任何异步操作之前使用“await”关键字。此操作将返回一个 Future 对象,该对象表示未来某个时刻可用的潜在值。您也可以使用“then()”来实现相同的目的,但使用回调。

在同步语言中,您可能会这样:

String user = new Database.fetch(David);
String personalData = new Database.fetch(user);

您将在用户中收到大卫的数据,之后您将收到您的数据。这将阻止您正在执行的所有操作,直到结果准备就绪。这可能会导致冻结和性能问题。

在多线程语言中,您可以创建一个新线程,并将任务委托给它,这将在并发线程中执行(这不会发生在 dart 或 javascript 中,因为它们是单线程)。

如果您在 Dart 或 javascript 中执行此操作

String user = new Database.fetch(David);
String personalData = new Database.fetch(user);
// (Update note: when I wrote this answer dart still used "new",
// nowadays you don't need and shouldn't use it, in javascript yes.)

user 在 PersonalData 中将为 null,因为 fetch 事件是 Future。

在 Dart 中如何解决这个问题?

String user = await Database.fetch(David);
String personalData = await Database.fetch(user);

你已经告诉 dart 你要等待结果fetch异步地。

您可以使用回调来实现相同的目的then,虽然我个人不喜欢这样。

Database.fetch(David).then((user){
  Database.fetch(user).then((personal){
    String personalData = personal;
  });
});

所以使用await会让dart像多线程语言一样表现出惊人的性能,对吗?错误的!!!!,即使 dart 异步运行它(这比阻塞同步更好),您仍然在主线程中运行它!如果您因繁重的任务而超载,您的 UI 仍然可能崩溃! 想象一下,您的数据库中有数十亿的数据,这项繁重的任务可能会导致屏幕上的动画冻结,并且您会在用户的 UI 中看到卡顿,为此目的发明了隔离。

Dart Isolates 为您提供了一种执行多线程类系统的方法。它们有自己独立的堆(内存),并在后台运行代码,类似于多线程语言的Thread。我可以解释隔离是如何工作的,但这会使这个响应变得很长,而且目标只是区分异步和多线程方法。

在 Flutter 中使用隔离来解决上述问题的一个简单方法是使用compute.

创建计算是为了方便创建隔离,您只需传递函数和该函数将执行的数据,就是这样! 重要的是要记住计算是未来,所以你必须使用await or then得到它的结果。

在我们的示例中,我们可以创建一个新线程,并在完成时通过调用计算来获取其结果,如下所示:

String user = await compute(Database.fetch,David);
String personalData = await compute(Database.fetch,user);

很简单,不是吗?

总之: 在 Dart 中,所有等待一段时间才能完成的东西都被称为“Future”。 要等待将 future 的结果分配给变量,请使用await or then。 异步方法(await and then) 可用于从 Future 获取结果,并且在主线程上执行,因为 Dart 是单线程的。 如果你想在新线程上运行任何函数,你可以创建一个isolate。 Flutter 提供了一个易于使用的隔离包装器,称为compute,你只需要传递一个将要处理的方法和将要处理的数据,它就会在将来返回它的结果。

  • 注意:如果您要使用计算,请确保您使用的是静态或顶级方法(请参阅在我使用 Database.fetch 的示例中,如果您需要调用 Database().fetch 或需要创建,这并非偶然它的一个实例,意味着它不是静态方法,并且不能与隔离一起使用)。

好吧,如果 dart 提供了isolate,那么它不应该被认为是多线程的吗? 好吧,Dart 提供了一种使用隔离创建并发计算的方法,但需要注意的是,Dart 中的隔离与其他编程语言中的线程不同。 隔离 != 线程

在 Dart 中,每个隔离区都有自己的内存堆,隔离区之间的通信通过消息传递进行,这与传统多线程中使用的共享内存模型不同。这意味着隔离可以彼此独立运行并且不共享可变状态,这可以帮助避免多线程程序中可能出现的一些并发问题(当您想要在隔离之间共享状态时,有时可能会令人头痛) )

因此,虽然 Dart 可能不是严格意义上的多线程语言,但它确实提供了强大的并发模型,可以帮助您创建可扩展且高效的应用程序,但这并不能使其成为多线程语言,因为它实际上并不具有多线程,它具有多线程,尽管它们的行为方式可能相似,但也有其特殊性。

英语不是我的母语,但我希望我能帮助区分多线程异步编程和单线程异步编程。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我在 Flutter/Dart 异步代码执行方面遇到问题,例如它是如何工作的 的相关文章

随机推荐

  • 剧作家 + Django:如何等待事件

    在我的测试中 我必须等待事件触发才能继续测试断言 但我不知道如何让 Playwright 等待该事件 剧作家似乎看不到该事件 django 页面的简单示例 单击按钮会触发事件boop改变文档的背景颜色 模板event html
  • ajax在asp.net中的使用

    我对使用哪种方法有点困惑 1 使用Jquery调用实现订单的HttpHandler页面 2 使用 ICALLBACKEventHandler 阅读更多 http www ajaxmatters com 2006 05 using icall
  • Meteor如何在mongo中保存模板

    我想让我的用户能够创建文档模板 合同 电子邮件等 我想出的最好的选择是将这些文档模板存储在 mongo 中 也许我错了 我已经搜索了几个小时 但我不知道如何使用它们的数据上下文呈现这些文档模板 Example Template stored
  • Jupyter 编辑模式下是否有删除行的快捷方式?

    In Jupyter s edit mode is there a shortcut for deleting a line of text Something like Ctrl L in Visual Studio Shift Dele
  • 如何确保分页 REST API 中的数据完整性?

    我目前正在研究 REST API API返回的资源预计是来自数据库的海量数据 数据库中有数千万行 分页是必须的 以避免将数据写入 HTTP 响应时消耗大量内存 当客户端请求之间数据库中存在删除 添加行时 如何确保数据完整性 例如 page
  • Android 共享首选项的空指针异常

    我试图在共享首选项中保存一个整数值 并在应用程序重新启动时再次加载它 我在我的主要活动中创建了一个共享首选项 并尝试在单击菜单项时在另一个菜单侦听器类中保存整数值 菜单侦听器类位于不同的包中 并且菜单侦听器类扩展了主活动 但是当我尝试这样做
  • 如何使 GCC 将 .text 部分编译为 ELF 二进制文件中的可写部分?

    我希望能够动态更改我正在使用的库中的可执行代码 本质上 我想动态地 NOP 掉某些不需要的函数 但是 我正在使用的库的 text 部分是不可写的 大多数程序都是如此 我有该库的源代码 因此想使用 GCC 将其编译为可写 有没有办法做到这一点
  • Linq to SQL 如何执行“where [column] in (值列表)”

    我有一个函数 可以获取 id 列表 并且需要返回与该 id 关联的描述相匹配的列表 例如 public class CodeData string CodeId get set string Description get set publ
  • 如何调整 vb6 程序的大小,使其自动适应任何屏幕分辨率?

    我怎样才能有一个在 1280 1024 下正确打开的 vb6 程序 但当切换到其他分辨率 例如 640 480 时 我只能看到一半的屏幕 如何重新调整我的 vb6 程序的大小 以便它自动适合任何屏幕分辨率 您需要使用Screen对象 这将始
  • 更改 Html.DisplayFor 布尔复选框 MVC

    我有一个布尔属性 IsActive 视图中是对象及其属性 包括 IsActive 的列表 但在列表中 IsActive 是一个不可编辑的复选框 因为它是布尔值 如果我将 DisplayFor 更改为 DisplayTextFor 那么它将只
  • Excel VBA:合并循环内的范围

    I want to merge that repeating Chapters into just one cell by Chapter 这是我的代码如何进行循环的 Dim label As Control Dim itm As Obje
  • C中最好的计时方法?

    以高分辨率和可移植性对代码部分进行计时的最佳方法是什么 Time from here ProcessIntenseFunction to here printf Time taken d seconds d milliseconds sec
  • Maven Tycho:如何在产品构建中排除 eclipsec.exe?

    我将 Eclipse RCP 产品的构建从 PDE 构建切换到 Maven Tycho 除了主 品牌 启动器可执行文件之外 该产品现在还包括 eclipsec exe 文件 我们希望从我们的产品中省略这个基于控制台的启动器 因为它可能会让我
  • LinkedIn API 获取公司所有员工吗?

    是否可以获取公司所有员工的名单 不仅在当前用户网络中 就像这样的搜索返回 http api linkedin com v1 people search company name Apple 这在 LinkedIn 主网站上是可能的 所以我不
  • 在自定义验证属性中使用数据库上下文

    我正在尝试在我的 Core 2 项目中创建一个验证属性 它需要根据数据库中保存的现有值列表来验证该值 下面的代码不起作用 它无法访问数据库上下文 有什么想法为什么 如何纠正吗 public class BibValidatorAttribu
  • typeid 运算符返回的对象的生命周期是多少?

    如果我打电话typeid并检索返回的地址type info const type info info typeid Something 返回的对象的生命周期是多少typeid指向该对象的指针将保持有效多久 然而 实施实施了它们 结果type
  • R 箱线图频率

    我需要帮助 我正在使用R分析一些数据 我有一个名为 mytable 的频率表 我创建的如下 mytable table cut var1 12 cut var2 12 该表看起来像这样 1 2 2 3 3 4 1 3 2 1 2 3 6 0
  • IBM DB2 中的数据类型转换:BIGINT 到 VARCHAR

    我正在编写一个查询来做一些事情 但它没有按照我想要的方式工作 select CORR ID from TABLE1 where CORR ID not in select id from TABLE2 问题是 TABLE2 id 是一个 l
  • Cloud Functions for Firebase 可以跨项目使用吗?

    我希望每当新的 Pub Sub 消息发送到第三方项目 即跨项目 中的主题 订阅时触发 Pub Sub 函数 使用functions pubsub onPublish 经过一些研究和实验 我发现如果主题名称包含 并且默认为 projects
  • 我在 Flutter/Dart 异步代码执行方面遇到问题,例如它是如何工作的

    在 Flutter 中 我们使用 async wait 和 Future 有人可以解释一下 如果我们不使用另一个线程 在 dart 中不能这样做 并仅在主 UIThread 上运行作业 应用程序不会变得不稳定 因为即使我们等待作业执行它最终