草庐IT

c# - C# 5.0 的异步等待功能与 TPL 有何不同?

coder 2023-07-08 原文

我看不出 C#(和 VB)的新异步特性和 .NET 4.0 的 Task Parallel Library 之间有什么不同.以 Eric Lippert 的代码 from here 为例:

async void ArchiveDocuments(List<Url> urls) {
    Task archive = null;
    for(int i = 0; i < urls.Count; ++i) {
        var document = await FetchAsync(urls[i]);
        if (archive != null)
            await archive;
        archive = ArchiveAsync(document);
    }
}

await 关键字似乎有两个不同的用途。第一次出现 (FetchAsync) 似乎意味着,“如果此值稍后在方法中使用并且其任务未完成,请等到它完成后再使用继续。” 第二个实例 (archive) 似乎意味着,“如果此任务尚未完成,请立即等待它完成。 " 如果我错了,请纠正我。

这样写不就这么简单吗?

void ArchiveDocuments(List<Url> urls) {
    for(int i = 0; i < urls.Count; ++i) {
        var document = FetchAsync(urls[i]);       // removed await
        if (archive != null)
            archive.Wait();                       // changed to .Wait()
        archive = ArchiveAsync(document.Result);  // added .Result
    }
}

我将第一个 await 替换为实际需要值的 Task.Result ,将第二个 await 替换为 Task.Wait(),实际发生等待的地方。该功能 (1) 已经实现,并且 (2) 在语义上更接近于代码中实际发生的事情。

我确实意识到 async 方法被重写为状态机,类似于迭代器,但我也看不出这会带来什么好处。任何需要另一个线程才能运行的代码(例如下载)仍将需要另一个线程,而任何不需要另一个线程的代码(例如从文件中读取)仍然可以利用 TPL 仅与单个线程一起工作。

我显然在这里遗漏了一些重要的东西;谁能帮助我更好地理解这一点?

最佳答案

我认为误解出现在这里:

It seems that the await keyword is serving two different purposes. The first occurrence (FetchAsync) seems to mean, "If this value is used later in the method and its task isn't finished, wait until it completes before continuing." The second instance (archive) seems to mean, "If this task is not yet finished, wait right now until it completes." If I'm wrong, please correct me.

这实际上是完全错误的。两者含义相同。

在你的第一种情况下:

var document = await FetchAsync(urls[i]);

这里发生的事情是,运行时说“开始调用 FetchAsync,然后将当前执行点返回给调用此方法的线程。”这里没有“等待”——相反,执行返回到调用同步上下文,并且事情一直在搅动。在未来的某个时刻,FetchAsync 的 Task 将完成,此时,此代码将在调用线程的同步上下文中恢复,并且下一个语句(分配文档变量)将发生。

然后执行将继续,直到第二次等待调用 - 此时,同样的事情会发生 - 如果 Task<T> (存档)未完成,执行将被释放到调用上下文 - 否则,存档将被设置。

在第二种情况下,情况非常不同 - 在这里,您显式阻塞,这意味着调用同步上下文永远不会有机会执行任何代码,直到您的整个方法完成。当然,仍然存在异步,但异步完全包含在此代码块中 - 在您的所有代码完成之前,此线程上不会发生此粘贴代码之外的任何代码。

关于c# - C# 5.0 的异步等待功能与 TPL 有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4054263/

有关c# - C# 5.0 的异步等待功能与 TPL 有何不同?的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  4. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  7. ruby-on-rails - 为什么方法 column_types 在 Rails 5.0 中未定义? - 2

    我正在为一个类赋值,它在rspec测试中使用了column_types方法。it"Userdatabasestructureinplace"doexpect(User.column_names).toinclude"password_digest","username"expect(User.column_types["username"].type).toeq:stringexpect(User.column_types["password_digest"].type).toeq:stringexpect(User.column_types["created_at"].type).t

  8. ruby-on-rails - rails 功能测试 - 2

    在Rails自动生成的功能测试(test/functional/products_controller_test.rb)中,我看到以下代码:classProductsControllerTest我的问题是:方法调用products()在哪里/如何定义?products(:one)到底是什么意思?看代码,大概意思是“创建一个产品”,但是它是如何工作的呢?注意我是Ruby/Rails的新手,如果这些是微不足道的问题,我深表歉意。 最佳答案 如果您查看test/fixtures文件夹,您会看到一个products.yml文件。这是在您创建

  9. ruby-on-rails - 功能测试 Authlogic? - 2

    在我的一些Controller中,我有一个before_filter检查用户是否登录?用于CRUD操作。application.rbdeflogged_in?unlesscurrent_userredirect_toroot_pathendendprivatedefcurrent_user_sessionreturn@current_user_sessionifdefined?(@current_user_session)@current_user_session=UserSession.findenddefcurrent_userreturn@current_userifdefine

  10. c# - C# 中的 Flatten Ruby 方法 - 2

    我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume

随机推荐