异步编程和多线程有什么区别?

2023-12-05

我认为它们基本上是同一件事——编写在处理器之间分配任务的程序(在具有 2 个以上处理器的机器上)。然后我在读书this,其中说:

异步方法旨在成为非阻塞操作。等待 异步方法中的表达式不会阻塞当前线程,而 等待的任务正在运行。相反,该表达式签署了其余部分 该方法作为延续并将控制权返回给调用者 异步方法。

async 和await 关键字不会导致额外的线程 创建的。异步方法不需要多线程,因为异步方法 方法不在自己的线程上运行。该方法在当前运行 同步上下文并仅在以下情况下使用线程上的时间: 方法处于活动状态。您可以使用 Task.Run 将 CPU 密集型工作移至 后台线程,但后台线程对进程没有帮助 只是等待结果出来。

我想知道是否有人可以帮我将其翻译成英语。它似乎在异步性(这是一个词吗?)和线程之间进行了区分,并暗示您可以拥有一个具有异步任务但没有多线程的程序。

现在我理解了异步任务的想法,例如 pg 上的示例。 467 乔恩·斯基特的C# 深入探讨,第三版

async void DisplayWebsiteLength ( object sender, EventArgs e )
{
    label.Text = "Fetching ...";
    using ( HttpClient client = new HttpClient() )
    {
        Task<string> task = client.GetStringAsync("http://csharpindepth.com");
        string text = await task;
        label.Text = text.Length.ToString();
    }
}

The async关键字的意思是“无论何时调用此函数,都不会在调用该函数后的所有内容都需要完成该函数的上下文中调用。”

换句话说,在某个任务的中间编写它

int x = 5; 
DisplayWebsiteLength();
double y = Math.Pow((double)x,2000.0);

, since DisplayWebsiteLength()与以下无关x or y, 会引发DisplayWebsiteLength()“在后台”执行,例如

                processor 1                |      processor 2
-------------------------------------------------------------------
int x = 5;                                 |  DisplayWebsiteLength()
double y = Math.Pow((double)x,2000.0);     |

显然这是一个愚蠢的例子,但我是正确的还是我完全困惑了还是什么?

(另外,我也很困惑为什么sender and e从未在上述函数体内使用过。)


你的误解非常普遍。许多人被告知多线程和异步是同一件事,但事实并非如此。

类比通常会有所帮助。你正在一家餐馆做饭。一份鸡蛋和吐司的订单进来了。

  • 同步:先煮鸡蛋,然后煮吐司。
  • 异步、单线程:您开始煮鸡蛋并设置计时器。您开始烤面包,并设置计时器。当他们俩做饭时,你打扫厨房。当计时器响起时,您将鸡蛋从火上取下,将吐司从烤面包机中取出并享用。
  • 异步、多线程:您再雇用两名厨师,一名负责煮鸡蛋,一名负责烤面包。现在你面临着协调厨师的问题,这样他们在共享资源时就不会在厨房里互相冲突。而且你必须付钱给他们。

现在,多线程只是异步的一种,这有意义吗?线程是关于工人的;异步是关于任务的。在多线程工作流程中,您将任务分配给工作人员。在异步单线程工作流程中,您有一个任务图,其中某些任务依赖于其他任务的结果;当每个任务完成时,它会根据刚刚完成的任务的结果调用调度下一个可以运行的任务的代码。但您(希望)只需要一名工人来执行所有任务,而不是每个任务一名工人。

这将有助于认识到许多任务不受处理器限制。对于处理器绑定的任务,雇用与处理器一样多的工作人员(线程)是有意义的,为每个工作人员分配一项任务,为每个工作人员分配一个处理器,并让每个处理器除了计算结果外不执行其他任何操作尽快。但对于不等待处理器的任务,您根本不需要分配工作人员。您只需等待结果可用的消息到达即可等待的时候做点别的事。当该消息到达时,您可以安排已完成的任务的继续,作为待办事项列表上要核对的下一件事情。

让我们更详细地看看乔恩的例子。会发生什么?

  • 有人调用 DisplayWebSiteLength。 WHO?我们不在乎。
  • 它设置一个标签,创建一个客户端,并要求客户端获取一些东西。客户端返回一个代表获取某些内容的任务的对象。该任务正在进行中。
  • 是否正在另一个线程上进行?可能不会。读斯蒂芬的文章关于为什么没有线程。
  • 现在我们等待任务。会发生什么?我们检查任务在创建任务和等待任务之间是否已完成。如果是,那么我们获取结果并继续运行。假设它尚未完成。我们将此方法的其余部分标记为该任务的延续并返回.
  • 现在控制权已返回给调用者。它有什么作用?随心所欲。
  • 现在假设任务完成。它是怎么做到的?也许它正在另一个线程上运行,或者我们刚刚返回的调用者允许它在当前线程上运行完成。无论如何,我们现在已经完成了任务。
  • 已完成的任务询问正确的线程——同样,可能是only线程——运行任务的延续。
  • 控制立即传回到我们刚刚在等待点留下的方法。现在那里is可用的结果,以便我们可以分配text并运行该方法的其余部分。

就像我的比喻一样。有人向您索要文件。您邮寄该文档,然后继续做其他工作。当邮件到达时,您会收到信号,当您愿意时,您可以完成其余的工作流程 - 打开信封,支付送货费,等等。您不需要雇用另一个工人来为您完成所有这些工作。

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

异步编程和多线程有什么区别? 的相关文章

  • 按成员序列化

    我已经实现了template
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐