2015-09-04 14 views
0

我不确定我是否正确提问,请耐心等待。这是我正在处理的:我在Task.Run(()=> MyTask).Result之间输了什么,等待MyTask和MyTask.Result?

在我的MVC4项目(targetting。净4.5.1)如果我做await SomeAsyncMethod(...),然后任务在后台完成,但似乎永远不会返回。我相信这与线程被返回到池然后在不同的线程上恢复有关。我一直在使用的解决方法是使用Thread.Run(() => SomeTask).Result;

所以,我发现自己必须在我的MVC项目中做很多Thread.Run(() => SomeAsyncMethod).Result;以免最终导致死锁。这不就是同步运行任务的另一种语法吗?我不确定这是否是MVC 4(与MVC 5)的限制,或者这只是api的工作原理。通过这样做,我在异步性方面基本上没有获得什么?我们已经写了一个小型库,其中所有的操作都是async Task<T>,它在一个单独的程序集中,所以至少我们可以在其他地方“正确地”使用它(例如窗口电话应用程序),但是此MVC 4项目是上述图书馆的消费者,感觉就像我们基本上在异步/等待中获益,以避免死锁,所以我在寻找帮助来看到这里的大局。这将有助于更好地理解我通过在同步管理器中使用异步任务(如果有的话),我失去了什么,如果有一个解决方案让我能够在不发生死锁的情况下等待这些任务,以及是否不是的情况是MVC 4 MVC 5+

TIA

+0

你可能想看看在http://stackoverflow.com/questions/13489065/best-practice-to-call-configureawait-for-all-server-side答案(和评论) -code – Jcl

回答

3

之间的不同。在我MVC4项目(靶向净4.5.1)如果我是在等待着SomeAsyncMethod(...),然后在任务完成在后台但似乎永远不会返回。

这几乎肯定是由于两件事之一。要么:

  1. 进一步向上调用堆栈的代码在任务上调用ResultWait。这将导致ASP.NET中的死锁。正确的解决方案是用await替换Result/Wait。我有更多的细节on my blog
  2. httpRuntim[email protected]未在web.config中设置为4.5或更高。这是从早期版本升级的ASP.NET项目的常见情况;您需要明确设置此值以使await正常工作。还有更多的细节in this blog post

所以,我发现自己不得不做Thread.Run(()=> SomeAsyncMethod)。结果;很多在我的MVC项目中,以免导致死锁。这不就是同步运行任务的另一种语法吗?

非常多。实际发生的是SomeAsyncMethod在线程池线程上运行,然后请求线程被阻塞,直到该方法完成。

我这样做对于异步性来说基本上什么都没有收获吗?

正确。事实上,你正在获得消极的好处。

服务器端异步的关键在于通过在不需要时释放请求线程来提高可伸缩性。 Task.Run(..).Result技术不仅可以防止请求线程被释放,还可以使用其他线程来完成实际的工作。所以它比仅仅同步做这件事更糟糕。

+0

我看到web.config没有将该属性添加到httpRuntime标记中。我现在添加它,然后再尝试等待。我有Task.Wait或Task.Run()的0个实例。后面我提到的结果。希望它开始行为正确 – Sinaesthetic

+0

这似乎已经修复它!我正在分解所有的包装方法。辉煌。谢谢! – Sinaesthetic

+1

@Sinaesthetic:不客气!仅供参考,如果您创建* new * MVC4/.NET4.5项目,则应正确设置'web.config'值;这只是已升级*的项目的一个问题。 –

0

加成@斯蒂芬的回答,我的2美分:

我相信这事做与线程返回到池中,然后在不同的线程恢复。

编辑: 不,这一切都发生在单个线程(通常是UI线程,在MVC它分配给请求线程的情况下)。异步等待消息泵的工作,这是一个在单线程上运行的无限循环。每等待都会向消息泵发出消息并检查消息是否完成。

以上并不完全适用于Asp.net。请参阅下面的@ Jeff的评论。

============================================= ============异步架构的

一个规则,如果是异步,保持它的异步一路。

创建基于异步方法同步封装经常导致阻塞主线,其中主线程和任务线程继续等待对方回应。

+0

这是错误的。自己等待没有做什么。在等待之后恢复对代码的控制权由同步上下文处理,该同步上下文必须决定分配哪个线程,无论是线程池,UI线程还是其他内容。在WebAPI V5中使用异步操作,异步感知不会在原始线程上恢复。它继续请求,可能在不同的线程 – Jeff

+0

可能我在这里不同步。我需要重新审视Async等待规格。这是我从阿西克等待释放的时候就知道的。或者我可能无法很好地表达这个想法。 – vendettamit

+1

Async和await仅仅是一个编译器技巧,它使用Tasks和Awaiters发出对TPL的调用。一个框架必须实现一个SychronizationContext来确保在等待时以适当的方式恢复控制 – Jeff

0

ASP .NET .NET MVC 4应该知道Actions上的async关键字,并且应该在使用await关键字时正确处理恢复请求。你确定使用await的有问题的Action返回一个Task并且不会尝试返回T本身吗?

这是通过使用SynchronizationContext的ASP .NET MVC处理的,以确保请求在等待后正确恢复,即使它在不同的线程上。

是的,如果你只是打电话。结果,它直到任务完成,你最终使用(可能)两个线程没有任何好处相同的请求阻塞调用线程。

http://www.asp.net/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4

相关问题