假设我有一个长时间运行的sql请求。它的数据应该序列化为JSON并发送到浏览器(作为xhr请求的响应)。示例代码:
public class DataController : ApiController { public Task<Data> Get() { return LoadDataAsync(); // Load data asynchronously? } }
当我做$ .getJson(‘api / data’,…)时会发生什么(见这个海报http://www.asp.net/posters/web-api/ASP.NET-Web-API-Poster.pdf):
> [IIS]请求被IIS接受。
> [IIS] IIS从管理池(http://msdn.microsoft.com/en-us/library/0ka9477y(v=vs.110).aspx)等待一个线程[THREAD]并开始工作。
> [THREAD] Webapi在该线程和其他类中创建新的DataController对象。
> [THREAD]使用任务并行库在[THREAD2]中启动SQL查询
> [THREAD]返回到受管池,准备进行其他处理
> [THREAD2]使用sql驱动程序,读取数据,准备好并调用[THREAD3]回复xhr请求
> [THREAD3]发送响应。
请随时纠正我,如果有什么问题。
在上面的问题,他们说,点和利润是,[THREAD2]不是从管理池,但MSDN文章(上面的链接)说,
By default,parallel library types like
Task
andTask<TResult>
use thread pool threads to run tasks.
所以我得出结论,所有三个THREADS是从管理池。
此外,如果我使用同步方法,我仍然保持我的服务器响应,只使用一个线程(从珍贵的线程池)。
那么,从1个线程切换到3个线程的实际点是什么?为什么不只是最大化线程池中的线程?
有什么明显有用的方法使用异步控制器?
解决方法
async
intro在我的博客,可以帮助。
特别地,由异步方法返回的任务不运行任何代码。相反,它只是一种方便的方法来通知呼叫者该方法的结果。您引用的MSDN文档仅适用于实际运行代码的任务,例如Task.Run。
BTW,你引用的海报与线程无关。下面是在异步数据库请求中发生的情况(略微简化):
>请求被IIS接受并传递给ASP.NET。
> ASP.NET使用其中一个线程池线程并将其分配给该请求。
> WebApi创建DataController等
>控制器操作启动异步SQL查询。
>请求线程返回到线程池。现在没有线程处理请求。
>当结果从sql服务器到达时,线程池线程读取响应。
>线程池线程通知请求它准备好继续处理。
>由于ASP.NET知道没有其他线程处理该请求,它只是分配同一个线程的请求,所以它可以直接完成它。
如果你想要一些概念验证代码,我有an old Gist人为限制ASP.NET线程池到核心数(这是它的最小设置),然后N 1同步和异步请求。该代码只是延迟一秒,而不是联系sql服务器,但一般的原则是一样的。