首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么在异步函数上使用Task.Run不返回Task<Task<T>>

在异步函数上使用Task.Run不返回Task<Task<T>>的原因是,异步函数本身已经返回了一个Task<T>对象,而不是一个Task<Task<T>>对象。Task.Run方法用于在后台线程上执行一个操作,并返回一个Task对象来表示该操作的异步执行。当我们在异步函数上使用Task.Run时,它会创建一个新的任务来执行该异步函数,并返回一个Task对象,该对象表示异步函数的执行状态和结果。

异步函数通常用于执行耗时的操作,例如网络请求或数据库查询。通过使用异步函数,我们可以在操作执行期间释放主线程,以便主线程可以继续响应用户输入和处理其他任务。异步函数使用async和await关键字来指示其异步执行的部分,并且返回一个表示操作结果的Task<T>对象。

Task.Run方法的作用是将一个操作调度到线程池上的新线程上执行,以便不阻塞当前线程。它接受一个委托作为参数,并返回一个Task对象。在异步函数上使用Task.Run的常见用法是在UI线程中调用异步函数,以确保UI线程不被阻塞。

由于异步函数本身已经返回了一个Task<T>对象,因此在异步函数上使用Task.Run不需要返回Task<Task<T>>。返回Task<Task<T>>将导致编译错误,因为返回类型与异步函数的返回类型不匹配。

总结起来,异步函数已经返回了一个Task<T>对象,Task.Run方法用于在后台线程上执行异步函数,并返回一个Task对象。因此,在异步函数上使用Task.Run不需要返回Task<Task<T>>。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Asp.Net Core 轻松学-多线程之Task快速上手

Task使用方法 Task使用用方法非常简单,一行代码就可以开始一个异步任务 1.1 最简单的使用方式 static void EasyTask() {...// 执行一个无返回值的任务 Task.Run(() => { Console.WriteLine("runing..."...return new Random().Next(); }); // 声明一个任务,仅声明,执行 Task t = new Task...,先不要去深究其背后的原理,对于新手来说,先解决能用,再去了解为什么可以这样使用,不然,一开始就失去了学习的信心 2.1 使用 TaskFactory 工厂开始异步任务 static void Factory...同步上下文 WinForm/WPF 应用程序中,也常常需要在 UI 上开辟异步任务,通常情况下,窗体控件仅允许创建其的线程访问,没有 Task 的时代,处理异步上下文到同步上下文是一件非常复杂的事情

1.5K20

C#asyncawait 结构

异步方法:执行完成前立即返回调用方法,调用方法继续执行的过程中完成任务。 语法分析: (1)关键字:方法头使用 async 修饰。...(3)返回类型:只能返回 3 种类型(void、TaskTask)。TaskTask 标识返回的对象会在将来完成工作,表示调用方法和异步方法可以继续执行。...关于 async 关键字:   ①返回类型之前包含 async 关键字   ②它只是标识该方法包含一个或多个 await 表达式,即,它本身创建异步操作。   ...实际上,你并不需要构建自己的 awaitable,一般只需要使用 Task 类,它就是 awaitable。   最简单的方式是方法中使用 Task.Run() 来创建一个 Task。...【注意】它是不同的线程上执行方法。 介绍异步方法的语法、三种不同的返回值类型(void、TaskTask)和控制流程等。 简单常用的异步执行方式:Task.Run()。

3.3K80

.NET Core多线程 (3) 异步 - 下

Result => 同步等待,它其实违背了异步编程的理念(初心) 同步+异步混用会异常复杂,产生的Bug不易发现 比如:WindowsForm下,同步调用异步方法(task.GetResult...用线程池中的thread执行(比如:Task.Run),不用 main thread。...Wait 针对无返回值,可以帮助捕获到;ExceptionResult 针对有返回值,可以帮助捕获到Exception; 问题2:为什么得到的是AggregateException异常?...方式1:处理 if(t.IsFaulted) { t.Exception.Handle(m => true); } 方式2:处理,往外抛 if(t.IsFaulted) { t.Exception.Handle...异步编程中可能会出现异常逃逸现象,如何全局发现那些被我们忽视的异常Task? 解法:借助Finalize线程,回收托管资源时,调用析构函数。

21310

C# 使用Task执行异步操作

https://www.cnblogs.com/ryanzheng/p/10963966.html 为什么使用 Task Task 和 Thread 区别 Task 介绍 Task 简单实现 Task...执行状态 为什么使用 Task 线程是创建并发的底层工具,因此具有一定的局限性。...相反,只能联合(Join)它(进程阻塞当前线程)。 任务是可组合的——使用延续将它们串联在一起。...Task 介绍 Task 类的表示单个操作返回一个值,通常以异步方式执行。Task 对象是一个的中心思想 基于任务的异步模式 首次引入.NET Framework 4 中。...因为由执行工作 Task 对象通常以异步方式执行在线程池线程上而不是以同步方式主应用程序线程,您可以使用 Status 属性,以及 IsCanceled, ,IsCompleted, ,和 IsFaulted

2.7K10

C#中关于Task.Yeild()的探究

与同事讨论async/await内部实现的时候,突然想到Task.Yeild()这个函数,为什么呢,了解一点C#async/await内部机制的都知道,await一个异步任务(函数)的时候,它会先判断该...Test2()异步函数由于await了一个未完成的任务(1ms对于CPU来说是很长的了),所以会返回调用方,然后打印相同的时间,一秒钟之后会打印执行完毕。...(1, 1); //Task.Run()方法默认使用线程池任务调度器执行任务,由于主线程不是线程池线程,所以使用Task.Run() var t = Task.Run(async (...) => { var t1 = OP1(); var t2 = OP2(); await Task.WhenAll(t1, t2);...}); await t; Console.ReadLine(); } 可以看出OP1()和OP2()两个协程(Task)互相争用一个线程(用户模式下的CPU),如果主动让出执行权

27320

C#异步使用要点(翻译)

异步操作时需要注意的要点 1.使用异步方法返回值应当避免使用void 使用异步方法中最好不要使用void当做返回值,无返回值也应使用Task作为返回值,因为使用void作为返回值具有以下缺点 无法得知异步函数的状态机什么时候执行完毕...void,所以调用此方法时无法捕捉异常,使得进程崩溃 throw new Exception("异常了"); await Task.Run(() => { }); } 应该将异步函数返回...(() => { }); } 注:事件是一个例外,异步事件也是返回void 2.对于预计算或者简单计算的函数建议使用Task.FromResult代替Task.Run 对于一些预先知道的结果或者只是一个简单的计算函数...,使用Task,FromResult要比Task.Run性能要好,因为Task.FromResult只是创建了一个包装已计算任务的任务,而Task.Run会将一个工作项在线程池进行排队,计算,返回.并且使用...,执行waiting或者处理某些数据,此类线程建议使用Task.Run方法执行,因为Task.Run方法是将任务在线程池内进行排队执行,如果线程池线程进行长时间堵塞,会导致线程池增长,进而浪费性能,所以如果想要运行长时间的工作建议直接创建一个新线程进行工作

3.3K50

使用异步操作时的注意要点(翻译)

异步操作时需要注意的要点 1.使用异步方法返回值应当避免使用void 使用异步方法中最好不要使用void当做返回值,无返回值也应使用Task作为返回值,因为使用void作为返回值具有以下缺点 无法得知异步函数的状态机什么时候执行完毕...void,所以调用此方法时无法捕捉异常,使得进程崩溃 throw new Exception("异常了"); await Task.Run(() => { }); } ☑️应该将异步函数返回...(() => { }); } 注:事件是一个例外,异步事件也是返回void 2.对于预计算或者简单计算的函数建议使用Task.FromResult代替Task.Run 对于一些预先知道的结果或者只是一个简单的计算函数...,使用Task,FromResult要比Task.Run性能要好,因为Task.FromResult只是创建了一个包装已计算任务的任务,而Task.Run会将一个工作项在线程池进行排队,计算,返回.并且使用...使用async/await来代替返回Task时,还有性能上的考虑,虽然直接Task会更快,但是最终却改变了异步的行为,失去了异步状态机的一些好处 使用场景 1.

4.6K20

.Net异步编程知多少

可以看见,使用Task我们不必理会具体线程的创建。 我们也可以使用.NET 4.5引入的Task.Run静态方法来启动一个线程。...被async标记的方法,意味着可以方法内部使用await,这样该方法将会在一个await point(等待点)处被挂起,并且等待的实例完成后该方法被异步唤醒。...【注意:await point(等待点)处被挂起,并不是说代码中使用await SomeMethodAsync()处就挂起,而是进入SomeMethodAsync()真正执行异步任务时被挂起,切记,...async标记的方法,返回值类型为void、TaskTask。 被async标记的方法,方法的执行结果或者任何异常都将直接反映在返回类型中。...从代码中我们可以清楚看见,去取task返回值时,程序回去判断对应的任务是否执行完毕(IsCompleted),若没有则继续等待,也就是InternalWait方法中执行等待,而InternalWait

83470

C# Task.RunTask.Factory.StartNew 区别 创建新线程等待线程长时间运行

有小伙伴问我,为什么推荐他使用 Task.Factory.StartNew ,因为 Task.Run 是比较新的方法。...只需要知道 Task.Run dotnet framework 4.5 之后才可以使用,但是 Task.Factory.StartNew 可以使用Task.Run 更多的参数,可以做到更多的定制...可以认为 Task.Run 是简化的 Task.Factory.StartNew 的使用,除了需要指定一个线程是长时间占用的,否则就使用 Task.Run 创建新线程 下面来告诉大家使用两个函数创建新的线程...,但是Task.Run比较好看,所以推荐使用Task.Run。...); 使用 WaitAll 是调用 WaitAll 的线程等待,也就是先在线程 1 运行,然后异步到 线程2 运行,这时线程1 等待线程2运行完成再继续,所以输出 开始 线程1 进入 线程2 退出 线程

5.1K10

从 ThreadLocal 到 AsyncLocal

前些天跟大佬们群里讨论如何在不使用构造函数,增加方法参数的情况下把一个上下文注入到方法内部使用,得出的结论是 AsyncLocal 。...我们现在更多的时候会使用 async/await Task 来帮我们做多线程异步操作。...至于为什么,如果理解 Task 的原理,其实也很好理解。简单来说,Task异步是一种基于状态机实现方式,编译器碰到 await 会把代码编译成一个代码块,表示一种状态。...让我们使用另外一个代码实例来演示下 AsyncLocal 的特性。上面的代码演示的是一个 Task 接一个 Task 的场景,一下我们演示下 Task 嵌套 Task 的场景。...AsyncLocal 的变量值会被隔离每个 Task 流程内,就算嵌套,子流程对变量的修改也不会影响到父流程的值。 AsyncLocal 实用 AsyncLocal 的特性说的差不多了。

46220

C#5.0新增功能01 异步编程

大多数情况下模型十分简单: 对于 I/O 绑定代码,当你 await 一个操作,它将返回 async 方法中的一个 TaskTask。...执行伤害计算的开销可能极大,而且 UI 线程中执行计算有可能使游戏计算执行过程中暂停! 此问题的最佳解决方法是启动一个后台线程,它使用 Task.Run 执行工作,并 await 其结果。...如果你的工作为 I/O 绑定,请使用 async 和 await (而不使用 Task.Run)。 不应使用任务并行库 。 相关原因在深入了解异步的文章中说明。...async void 是允许异步事件处理程序工作的唯一方法,因为事件不具有返回类型(因此无法利用 TaskTask)。...请仅依赖方法的返回值。 为什么? 这样更容易推断代码。 这样更容易测试代码。 混合异步和同步代码更简单。 通常可完全避免争用条件。 通过依赖返回值,协调异步代码可变得简单。

2.3K20

C# 多线程(18):一篇文章就理解async和await

异步操作完成后,await 运算符将返回操作的结果(如果有)。 好的,到此为止,async 和 await ,官方文档中的说明,就这么多。...这里我们参考文档和书籍的资料,不要看文档和书籍中的示例,我们要一步步来从任务(Task)中的同步异步开始,慢慢摸索。...于是我们将洗衣服这个任务,封装到一个方法中,然后返回 Task 即可。 Program 类中,加入如下一个方法,这个方法用于执行异步任务,并且返回 Task 对象。...答:同步异步都行,要同步还是异步,全掌握在你的手上。 你使用 await 去调用一个异步方法,其执行过程就是同步。 你获取异步方法返回Task,就是异步。...Task封装异步任务 前面,我们都是使用了 new Task() 来创建任务,而且微软官网大多使用 Task.Run() 来编写 async 和 await 的示例。

3.3K62

C#进阶——从应用上理解异步编程的作用(async await)

,阻塞主线程 //拉姆达表达式开异步线程 //return await Task.Run(() => //{...string str = await Task.Run(Work); //步骤6:这里开线程处理耗时工作,阻塞主线程,主线程回到步骤3 //以下步骤都在等待...; //return await Task.Run(Work); } /// /// 耗时工作...那为啥叫异步呢,因为执行到await时不发生阻塞,直接跳过等待去执行其他的,当await返回时,又接着执行await后面的代码,这一系列的运行都是主调线程中完成,并没有开线程等待。...所以如果耗时函数不开一个线程运行,一样会阻塞,没有完全利用异步的优势。 那么,await是主线程等待,那其为什么没有阻塞主线程呢?我个人觉得其是利用委托的方式,后面再去揪原理吧!

65530

C#:异步编程中的 async 和 await

返回使用 async 标记的异步方法可以有四种类型的返回值: void Task Task ValueTask void 推荐使用,有下面几个原因: 因为使用 void 无法确定方法什么时候调用完成...; 返回 void 的异步方法没有办法调用的时候使用 await ; 无法处理异常。...Task 没有返回值的异步方法,我们应该返回 Task: 可以使用 Task 定义的变量来接收方法的返回值,该变量可以作为参数进行传递; 方法调用时可以使用 await 关键字; 可以捕获状态,看下面例子...Task异步方法需要返回一个值,给后面的步骤使用的的时候,就使用 Task调用的时候使用 Result 属性进行值的获取。...ValueTask ValueTask是 C#7.1 中推出的一种类型,使用 ValueTask 比 Task 更高效,该类型是一个 struct ,为值类型,栈上分分配,不像 Task 是个

2.4K20

.NET 异步详解

最典型的比如通过前后线程 ID 来推断其工作方式、 async 方法中用 Thread.Sleep 来解释 Task 机制而导出多线程模型的结论、 Task.Run 中包含 IO bound 任务来推出这是开了一个多线程执行任务的结论等等...Task.Run 由于 .NET 是允许有多个线程的,因此也提供了 Task.Run 这个方法,允许我们将 CPU bound 的任务放在上述的线程池之中的某个线程上执行,并且允许我们将该负载作为一个...这时有人要问了:“我 Task.Run 里面套了好几层 Task.Run,可是为什么层数深了之后里面的执行了呢?” 这是因为上面所说的线程池被耗尽了,后面的 Task 还在排着队等待被调度。...那我们要怎么样使用 Task 来编写我们自己的异步代码呢?...同步方式调用异步代码 说句真的,一般能有这个需求,都说明你的代码写的有问题,但是如果你无论如何都想以阻塞的方式去等待一个异步任务完成的话: Copy Task t = ... t.GetAwaiter(

69054
领券