首页
学习
活动
专区
工具
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.6K20
  • .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线程,在回收托管资源时,调用析构函数。

    25910

    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.9K10

    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.4K50

    C#asyncawait 结构

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

    3.3K80

    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),如果不主动让出执行权

    35720

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

    异步操作时需要注意的要点 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、Task、TaskT>。 被async标记的方法,方法的执行结果或者任何异常都将直接反映在返回类型中。...从代码中我们可以清楚看见,在去取task的返回值时,程序回去判断对应的任务是否执行完毕(IsCompleted),若没有则继续等待,也就是在InternalWait方法中执行等待,而InternalWait

    88670

    从 ThreadLocal 到 AsyncLocal

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

    54320

    C# Task.Run 和 Task.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.5K10

    C#的Task 和 Task

    在C#中,Task和TaskT>是实现异步编程的核心类型。它们允许开发者编写非阻塞代码,从而提高应用程序的响应性和吞吐量。...Task和TaskT>的基本概念1.1 什么是Task和TaskT>Task:表示异步操作,它不返回值。TaskT>:表示返回一个值的异步操作。...1.2 Task和TaskT>的特点非阻塞:允许程序在等待异步操作完成时继续执行其他代码。可组合:可以组合多个异步操作。易于错误处理:可以集中处理异步操作中的错误。2....Task和TaskT>的最佳实践4.1 避免在循环中使用await在循环中使用await可能会导致死锁。考虑使用Task.WhenAll来并行执行循环中的异步操作。... GetDataAsync() { await Task.Delay(1000); // 模拟异步操作 return 42; }}4.4 避免异步方法的返回值未使用确保异步方法的返回值被正确使用

    2.3K00

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

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

    2.4K20

    C#异步编程

    作为返回类型,若希望异步方法返回void类型,请使用Task 异步方法名称以Async结尾 异步方法中不能声明使用ref或out关键字修饰的变量 下面定义一个异步方法StartAsync(): static...("https://www.visualstudio.com/"); return str.Length; } 异步方法的返回类型 TaskT> 如果在调用匿名方法时使用了await关键字,且匿名方法的返回类型是...TaskT>,那么我们得到的返回类型是T。...若为使用await关键字,则得到的返回类型是Task。 void 不建议使用void作为异步方法的返回值。...Task Task类拥有执行异步方法的两个方法:Task.Run(),Task.RunT>,Task.Run以及Task.RunT>使用线程池中的线程来执行代码,它和使用await关键字的区别是:Task.Run

    96930

    C#异步编程

    作为返回类型,若希望异步方法返回void类型,请使用Task 异步方法名称以Async结尾 异步方法中不能声明使用ref或out关键字修饰的变量 下面定义一个异步方法StartAsync(): static...("https://www.visualstudio.com/"); return str.Length; } 异步方法的返回类型 TaskT> 如果在调用匿名方法时使用了await关键字,且匿名方法的返回类型是...TaskT>,那么我们得到的返回类型是T。...若为使用await关键字,则得到的返回类型是Task。 void 不建议使用void作为异步方法的返回值。...Task Task类拥有执行异步方法的两个方法:Task.Run(),Task.RunT>,Task.Run以及Task.RunT>使用线程池中的线程来执行代码,它和使用await关键字的区别是:Task.Run

    1K30

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

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

    69830

    技术速递|调用异步功能 - WinForms 在 .NET 9 中的未来发展

    方法会立即返回,使调用线程可以继续其工作。这种区别在异步场景中尤为重要,因为它允许应用程序同时处理其他任务而不产生延迟,从而最大限度地减少 UI 线程的瓶颈。...为什么这很重要 通过使用 InvokeAsync 发布委托,您的代码现在可以将多个更新排队到控件上,执行后台操作,或等待其他异步任务,而无需阻塞主 UI 线程。...我们获取 InvokeAsync 返回的 Task,然后将其传递给 Task.Run。轻松解决。 好吧——看起来并不太好。我们遇到了两个问题。...InvokeAsync 返回的是一个 Task,我们当然不能将其传递给 Task.Run。我们只能传递一个 Action 或返回 Task 的 Func,但绝不能直接传递一个 Task。...InvokeAsync wants a cancellation token, and we can't pass Task.Run a task. var invokeTask = this.InvokeAsync

    9110

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

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

    4.5K62

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

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

    2.6K21
    领券