.Net 任务类 - 请解释

     2023-04-11     88

关键词:

【中文标题】.Net 任务类 - 请解释【英文标题】:.Net Task class - please explain 【发布时间】:2015-09-05 01:12:27 【问题描述】:

谁能解释一下为什么下面的 public async Task DoStuff() 方法仍然可以工作而不返回任何东西?它没有说 void,所以我假设返回类型必须是 Task

当我从 DoStuff() 方法中删除 asyncawait 关键字时,编译器会给我一个 "not all代码路径返回值” 错误。但是,如果我添加 async 和 await 关键字,它似乎不需要返回类型,尽管方法签名中缺少 void 关键字。没看懂!

究竟什么是任务?微软解释得很糟糕。谢谢。

namespace Async_and_Await_Example

    class Program
    
        static void Main(string[] args)
        
            AsyncAwaitDemo demo = new AsyncAwaitDemo();
            demo.DoStuff();

            for (int i = 0; i < 100; i++)
            
                Console.WriteLine("Working on the Main Thread...................");
        
    

public class AsyncAwaitDemo

    public async Task DoStuff()
    
        await Task.Run(() =>
        
            CountToFifty();
        );
    

    private static async Task<string> CountToFifty()
    
        int counter;

        for (counter = 0; counter < 51; counter++)
        
            Console.WriteLine("BG thread: " + counter);
        

        return "Counter = " + counter;
    

【问题讨论】:

【参考方案1】:

为什么下面的 public async Task DoStuff() 方法仍然可以工作而不返回任何内容?

因为编译器允许这样做。当您使用 async 修饰符标记方法时,会创建一个状态机,它实际上会为您返回一个 Task。你可以在任何反编译器中看到它。

当我从 DoStuff() 方法中删除 async 和 await 关键字时,编译器会给我一个“并非所有代码路径都返回值”错误。

因为不再创建返回Task 的状态机,您现在必须自己做,因为没有更多的编译器魔法。

什么是任务?

正如其他人所说,只是对未来将完成的工作的承诺。 Task 可以代表很多东西,其中之一是异步操作。神奇之处在于旁边的async-await 关键字。编译器魔法与Task 有特殊关系,但任何实现GetAwaiter 方法的类型都可以等待。更多关于here

【讨论】:

【参考方案2】:

任务本质上是promise (or future)。它“承诺”你开始的异步方法最终会完成,完成任务。使用任务对象,以便您可以获取有关何时完成任务的信息。还有一个任务的generic version,它也简单地承诺在任务完成时你会得到一个值。

一旦你启动了一个异步方法,你就会得到一个Task 对象。该方法几乎立即返回,但实际工作可能稍后完成。然后您可以wait 让任务完成以阻塞当前线程并等待异步方法完成。

当您自己进行异步执行时(这通常是您在调用异步方法时想要执行的操作),那么您可以在任务对象上使用 await 关键字等待这些任务。这实质上会暂停您当前所在的异步方法,并在您等待的任务完成后立即返回执行。

await 关键字仅在异步方法中可用,由async 方法说明符表示。这些方法会自动返回一个任务对象作为返回值:如果你没有从异步方法显式返回任何东西,它会返回一个Task对象;如果你从异步方法返回一个T 类型的对象,它实际上会返回一个你可以等待的Task&lt;T&gt; 对象。一旦任务完成,Task&lt;T&gt; 类型就可以被“解包”。这使您可以获取T 类型的实际对象。

最后,async 方法也可以不返回任何内容,void,使它们“一劳永逸”。如果您调用返回类型为void 的异步方法,它将异步执行(“触发”),但您无法知道它何时完成,因为您没有要等待的任务对象(“忘记”)。这就是为什么您通常要避免使用async void 方法(它们对异常处理也不利)并始终使用“真正的”可等待异步方法(那些返回某些任务对象的方法)。但是您仍然可以使用async void 方法来启动异步执行而不会阻塞您的主线程。否则,您可以通过在任务上调用Wait() 方法来阻止它。

欲了解更多信息,请查看以下链接:

Asynchronous Programming with Async and Await Task-based Asynchronous Pattern Async/Await FAQ Async and Await

【讨论】:

【参考方案3】:

这是因为async/await 是魔法。好吧,这并不是真正的魔法,但是使用async/await,编译器正在重写您的方法,以便它返回Task。就像CountToFifty() 返回一个Task&lt;string&gt; 但你的方法返回一个string

Task 本身并没有什么特别之处。它只是一个普通的 .Net 类,用于表示可能尚未完成的操作。

如果没有 async/await,编译器不会修改 DoStuff(),因此它自己可以返回一个 Task 对象。

【讨论】:

【参考方案4】:

由于异步方法不会立即返回。方法可能需要查询外部源。这需要时间——其他代码也可以运行。这就是 Method 中 await-async 的目的。所以当我们使用 await 关键字时,并不总是需要在 Async Method 中返回。

查看Explanation of Tasks by DotNetPearls了解更多信息。

【讨论】:

【参考方案5】:

正如其他人所指出的,任务是“承诺”或“未来”——也就是说,它代表了将来可能完成的某些操作。

Task代表没有返回值的操作,Task&lt;T&gt;代表返回值为T的操作。

请注意,Task(而不是 void)很有用,因为操作可能成功完成,也可能出现异常(或取消),而 Task 能够表示这些结束状态。

谁能解释一下为什么下面的公共异步任务 DoStuff() 方法仍然可以在不返回任何内容的情况下工作?

async 关键字将为您的方法构造一个状态机,该状态机将创建一个代表该方法的Task 对象。如果您的async 方法返回一个值,则状态机将该返回值放在Task&lt;T&gt; 上。如果您的async 方法抛出异常,状态机将把该异常置于Task/Task&lt;T&gt;

什么是任务?

我已经在async/await 的上下文中描述了Task 是什么。部分混淆是因为Task 在以其他方式使用时具有非常不同的含义。我将术语 Promise Task 用于异步任务,将 Delegate Task 用于代码运行任务。

async 状态机创建的任务始终是 Promise 任务。一般来说,异步任务应该是await'ed,而不是Wait'ed。并且您应该避免使用async void(因为状态机无法表示该方法,它具有令人惊讶的异常处理语义)。

您可能会发现我的async intro 以及我的article on best practices 很有帮助。

【讨论】:

【参考方案6】:

另一种看法是,假设您有 4 件事要做以响应客户的 http 请求。

    在数据库中输入订单。 Task.Run(PlaceOrder) 向客户发送一封感谢邮件。 Task.Run(SendEmail) 向您的履行中心 API 发送请求。 Task.Run(PlaceOrder) 记录会话请求。 Task.Run(LogRequest)

因此,与其谈论合同、承诺、状态服务器等,Task 是一种将工作分散到所有内核/处理器上的线程。我有 4 个内核和 8 个处理器。如果我执行上述任务,我可以看到所有 8 个处理器都在运行,而且速度是原来的两倍多。这是一个任务。

它变得更好。这项工作现在在所有 8 个处理器上运行,但我们可以让它更快。尽管它们在所有 8 个处理器上运行,但它们轮流或排队等待对方完成。假设平均每个任务需要 5 秒,所以我对客户的响应时间是 20 秒,但我们只是将其缩短了一半。如果我使用 async/await,我可以同时推送所有 4 个任务,因此它们都不会相互等待。所以现在我可以看到所有 8 个处理器都在运行,但现在它们使用了更多的 cpu 和 wow64,它们已经完成了。

但是等待他们仍然很慢,因为发送订单的 api 请求需要 8 秒,客户和其他任务必须等待它完成。这是它变得非常好的地方。不要等待。回复客户并感谢他们的订单。因此,现在您只需在 3 毫秒而不是 20 秒内将交易转回给客户。围绕 4 个任务进行尝试/捕获并记录任何失败,以便有人可以处理它们。希望这已经完成,而不是告诉客户哦,抱歉我们的邮件服务器已关闭。我听说有些人称它为“忘记”之类的,这非常糟糕。不算太差。是很好的编程。扎实的主流线程/异步编程已经姗姗来迟。购买从未使用过的内核和内存,以及处理缓慢响应等待坦率地说他们不关心的事情的用户有望成为过去。

那是任务/异步/等待。

var myTask = Task.Run(() => doSomething );。

【讨论】:

请解释类方法

】请解释类方法【英文标题】:Pleaseexplainclassmethods【发布时间】:2012-06-0322:29:20【问题描述】:我很难理解何时需要创建类方法。根据我的阅读,它们对于创建新对象很重要,但我不明白如何。下面的类创建一个简单的黑色矩... 查看详情

.NET 4 任务类教程

】.NET4任务类教程【英文标题】:.NET4TaskClassTutorial【发布时间】:2011-04-2621:29:20【问题描述】:.NET4有一个类-Task。这很有趣,我想开始使用它。例如,我想创建一个非常简单的基于任务的文件下载器,每次下载都可以取消。谁... 查看详情

spark性能相关參数配置具体解释-任务调度篇

作者:刘旭晖Raymond转载请注明出处Email:colorantat163.comBLOG:http://blog.csdn.net/colorant/随着Spark的逐渐成熟完好, 越来越多的可配置參数被加入到Spark中来, 本文试图通过阐述这当中部分參数的工作原理和配置思路, 和大家... 查看详情

在 .NET Core 中使用 CQRS 与服务类的冗长任务 [关闭]

】在.NETCore中使用CQRS与服务类的冗长任务[关闭]【英文标题】:LengthytasksusingCQRSvsServiceclassin.NETCore[closed]【发布时间】:2022-01-0903:58:12【问题描述】:我正在.NETCore中开发一个项目,将Excel文件上传到MSSQL数据库。CQRS会是实现这个... 查看详情

wifimanager类具体解释

publicclassWifiManagerextends Objectjava.lang.Object   ?android.net.wifi.WifiManager类概述ThisclassprovidestheprimaryAPIformanagingallaspectsofWi-Ficonnectivity.Getaninstanceofthiscla 查看详情

机器学习具体解释svm解二分类,多分类,及后验概率输出

转载请注明出处:http://blog.csdn.net/luoshixian099/article/details/51073885CSDN?勿在浮沙筑高台color{Blue}{CSDN-勿在浮沙筑高台}支持向量机(SupportVectorMachine)以前在分类、回归问题中非常流行。支持向量机也称为最大间隔分类器,通过分离超平面... 查看详情

java中bufferedinputstream类相比inputstream类,提高了输入效率,增加了输入缓冲区的功能,请解释下,...

...Stream类,提高了输入效率,增加了输入缓冲区的功能,请解释下,谢谢。这个缓冲区的概念比较抽象,其实这么说就明白了不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所... 查看详情

.编写自定义任务类(代码片段)

本文禁止w3cschool转载!翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc 。本文翻译所在分支:https://github.com/msdx/gradledoc/tree/2.0 。更好的阅读体验请访问:http://gradledoc.githang.com/2.0/usergu 查看详情

.编写自定义任务类(代码片段)

本文禁止w3cschool转载!翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc 。本文翻译所在分支:https://github.com/msdx/gradledoc/tree/2.0 。更好的阅读体验请访问:http://gradledoc.githang.com/2.0/userguide/userguide.html 。... 查看详情

请解释为啥此代码打印 02002 而不是 00022

】请解释为啥此代码打印02002而不是00022【英文标题】:Pleaseexplainwhythiscodeprints02002andnot00022请解释为什么此代码打印02002而不是00022【发布时间】:2020-10-3111:35:23【问题描述】:我不明白为什么这段代码会打印02002而不是00022。据... 查看详情

关于transformer的面试题(代码片段)

...网络模型的区别。Transformer模型是否适用于非序列数据的任务?请举一个例子。请解释一下Transformer模型的训练过程中的损失函数是什么。请解释一下Transformer模型在自然语言处理领域的优势是什么?请描述一下如何使用Tr... 查看详情

a、b、c三类网络地址是如何划分的?请解释的通俗一点。

参考技术AABC三类地址用子网掩码划分A类地址:255.0.0.0B类地址:255.255.0.0C类地址:255.255.255.0255是网络位,0是主机位网络位和主机位怎样理解?网络位是需要检验的,怎样检验?比如192.168.10.100255.255.255.0这是一个C类网络掩码前三... 查看详情

Android 任务亲和说明

】Android任务亲和说明【英文标题】:AndroidTaskAffinityExplanation【发布时间】:2013-07-2605:30:52【问题描述】:taskAffinity属性究竟是做什么用的?我已经浏览了documentation,但我不太了解。谁能用通俗的方式解释任务亲和力?【问题讨... 查看详情

无法结束后台任务

】无法结束后台任务【英文标题】:Can\'tendBackgroundTask【发布时间】:2012-05-2314:50:50【问题描述】:我试图复制此博客中解释的内容,http://developer.blueearth.net/2011/12/02/quick-tip-clearing-up-ios-multitasking/,它解释了一种让NSTimer无休止地... 查看详情

.NET 4.5.1 跟踪所有取消任务?

】.NET4.5.1跟踪所有取消任务?【英文标题】:.NET4.5.1TrackallTasksforCancellation?【发布时间】:2014-03-1213:19:03【问题描述】:5个不相关的类实例执行Task.Run()以启动1-4个“做事”的实例。每个任务都有一个CancellationToken。让另一个对象... 查看详情

ado。net紧急!!!!高手请进。

ADO.NET有哪几个重要的组件?请简述它们的功能。ADO.NET是VisualStudio.NET中一个重要的数据库管理组件。它不是ADO为适应.NET基础构造而改进的版本,而是一个全新的访问编程模型。与原有的ADO组件不同,ADO.NET更具有通用性,不是专... 查看详情

请解释什么是axioutstanding,axioutoforder以及axiinterleaving?

AXIoutstanding:https://blog.csdn.net/tbzj_2000/article/details/88042890正常情况下的主机master和从机slave的操作是:读操作:主机发送读地址,从机返回数据,然后依次进行下去写操作:主机发送写地址和写数据,从机返回响应信号,依次进行ou... 查看详情

保存数据库控制器类 asp.net mvc5 身份中的更改

...有人帮助我如何通过控制器将信息保存在数据库中。让我解释一下......我希望发生以下情况:登录后的用户可以更新他的教育信息。在对字段进行 查看详情