Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我应该用Task.Run包装慢速呼叫吗?_C#_Asp.net Mvc_Async Await - Fatal编程技术网

C# 我应该用Task.Run包装慢速呼叫吗?

C# 我应该用Task.Run包装慢速呼叫吗?,c#,asp.net-mvc,async-await,C#,Asp.net Mvc,Async Await,我有一个ASP MVC调用,它是aync,因为它需要进行异步调用。我注意到有几个慢速同步调用(例如db访问)。该方法需要所有返回的数据都可用才能继续 我想用Task包装同步调用。运行并等待所有调用 打包慢速同步调用有意义吗?如果只有同步调用怎么办?如果任务是独立的(不依赖于其他任务的数据),并且可以独立执行,那么当然可以异步执行。如果它们是实体框架,并且是版本6,那么它提供了可调用的异步方法,您不必将它们包装在Task.Run中 即使任务不是独立的,您也可以对它们进行排序,使它们在执行时更加高效

我有一个ASP MVC调用,它是aync,因为它需要进行异步调用。我注意到有几个慢速同步调用(例如db访问)。该方法需要所有返回的数据都可用才能继续

我想用Task包装同步调用。运行并等待所有调用


打包慢速同步调用有意义吗?如果只有同步调用怎么办?

如果任务是独立的(不依赖于其他任务的数据),并且可以独立执行,那么当然可以异步执行。如果它们是实体框架,并且是版本6,那么它提供了可调用的异步方法,您不必将它们包装在Task.Run中

即使任务不是独立的,您也可以对它们进行排序,使它们在执行时更加高效

然而,是否使用Task.Run是一个重要的区别。Run将使用线程池线程,如果它正在执行同步操作,则线程池线程将被阻止,从而减少应用程序可用的线程池线程数。如果您有许多用户,并且正在执行许多任务,这可能是一个问题


尝试查找异步api,而不是使用Task.Run。

不要使用
Task.Run
来并行服务器端代码中的工作,除非您希望并发服务的客户端请求数量非常少。否则,您可能会加快单个请求的处理速度,但当有许多用户时,您的web应用程序的可伸缩性会受到影响

为了尝试扩展@Noseratio,旋转线程以“加速”同步工作的规模非常糟糕

需要记住的一点是,在ASP.NET中使用
Task.Run
是非常危险的,因为运行时不知道您正在排队等待需要完成的工作,IIS可能会不时尝试回收您的应用程序,这将导致工作意外中断


如果您使用的是.NET Framework 4.5.2,则有一个通过的解决方案。您可以在中阅读更多关于它的信息。如果不是,请阅读自定义实现。这两篇优秀的文章都是@StephanCleary写的

,使用async/await来允许保存当前线程,而不是等待处理请求,这难道不是重点吗?如果需要并行任务,那么他应该使用TPL,但是使用TAP应该有助于提高可伸缩性,而不是阻碍它。@RyanPeters,确实是这样,但是在服务器端环境中,您通常只对自然异步API使用TAP(查看Stephen Cleary的)。这样,HTTP请求的初始线程被释放到池中,然后可以服务于另一个HTTP请求。如果使用
Task.Run
,则不会释放线程。至于包装单个同步调用,这根本没有意义——您最好在当前线程上包装。至于并行包装多个调用,会损害可伸缩性。对于客户端UI应用程序,情况可能会有所不同,在客户端UI应用程序中,您不关心可伸缩性,而是关心UI线程的响应速度。@Noseratio-您只会在消耗和阻塞线程池线程的意义上损害可伸缩性,您不会占用额外的CPU资源,也不会占用最少的内存(线程池已经分配了,所以它的堆栈已经分配了)。虽然这确实可能是一个可伸缩性问题,但它实际上取决于许多因素,以确定这是否是一个问题。我同意,如果可能的话,从纯度的角度来看,如果没有其他问题的话,可能最好避免它。@ErikFunkenbusch,没错,但只是消耗(使用
Task.Run
)和阻塞池线程可能会对可伸缩性产生非常严重的影响。还有一种臭名昭著的
ThreadPool
口吃行为需要记住,下面是一些研究的结果。毕竟,为什么要加快单个客户机的请求处理(通过使用
Task.Run
分叉阻塞调用),而让其他客户机等待,因为没有空闲的池线程?我不认为作者在这里谈论的是提前返回。您谈论的是fire-and-forget或异步void方法,它们可能会导致您所谈论的问题。在这种情况下,他需要工作的结果,因此他必须等待它们完成,工人流程将不会得到回收。所以使用任务没有“危险”。这样运行,尽管@nosertio提到它对可伸缩性不是很好。他在等待这些任务,IIS没有理由不尝试回收eveb,尽管他在等待
。我说的不是异步作废或触发并忘记,我说的是使用
任务。通常在ASP.NET中运行
。如果主操作线程尚未完成并正在等待,除非超时,否则它不会回收。如果你不是在谈论火和遗忘,为什么你要引用这两篇关于它的文章呢?我认为@ErikFunkenbusch在这里有一个观点。也就是说,当执行点到达
async
webapi方法中的第一个
wait
时,将释放主操作线程(HTTP请求已到达要处理的初始线程)。但是,此时请求仍处于挂起状态(因为
wait
),因此IIS进程/appdomain不会被回收。在内部,跟踪。然而,像
wait Task.Run(DoWork)
这样的东西在ASP.NET中没有意义:它只是释放一个线程并获取另一个线程。