Tom*_*uλa 15 asp.net ihttpasynchandler threadpool task-parallel-library async-await
自从我想要添加线程时编写ASP.NET应用程序以来,我可以通过3种简单的方法在ASP.NET应用程序中完成线程化:
System.Threading.ThreadPool. BeginInvoke方法. System.Threading.Thread类的帮助下使用自定义线程.前两种方法提供了一种快速方法来为您的应用程序启动工作线程.但不幸的是,它们损害了应用程序的整体性能,因为它们使用ASP.NET使用的相同池中的线程来处理HTTP请求.
然后我想使用新的Task或async/await来编写IHttpAsyncHandler.您可以找到的一个例子是Drew Marsh在这里解释的:https://stackoverflow.com/a/6389323/261950
我的猜测是使用Task或async/await仍然消耗来自ASP.NET线程池的线程,我不想要显而易见的原因.
你可以告诉我,如果我可以在后台线程上使用Task(async/await),就像使用System.Threading.Thread类而不是线程池一样吗?
在此先感谢您的帮助.
托马斯
Ste*_*ary 17
这种情况是Task,async和await真正大放异彩.这是相同的示例,重构以充分利用async(它还使用我的AsyncEx库中的一些辅助类来清理映射代码):
// First, a base class that takes care of the Task -> IAsyncResult mapping.
// In .NET 4.5, you would use HttpTaskAsyncHandler instead.
public abstract class HttpAsyncHandlerBase : IHttpAsyncHandler
{
public abstract Task ProcessRequestAsync(HttpContext context);
IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
var task = ProcessRequestAsync(context);
return Nito.AsyncEx.AsyncFactory.ToBegin(task, cb, extraData);
}
void EndProcessRequest(IAsyncResult result)
{
Nito.AsyncEx.AsyncFactory.ToEnd(result);
}
void ProcessRequest(HttpContext context)
{
EndProcessRequest(BeginProcessRequest(context, null, null));
}
public virtual bool IsReusable
{
get { return true; }
}
}
// Now, our (async) Task implementation
public class MyAsyncHandler : HttpAsyncHandlerBase
{
public override async Task ProcessRequestAsync(HttpContext context)
{
using (var webClient = new WebClient())
{
var data = await webClient.DownloadDataTaskAsync("http://my resource");
context.Response.ContentType = "text/xml";
context.Response.OutputStream.Write(data, 0, data.Length);
}
}
}
Run Code Online (Sandbox Code Playgroud)
(如代码中所述,.NET 4.5具有HttpTaskAsyncHandler与HttpAsyncHandlerBase上面类似的内容).
该很酷有关的事情async是,它并不需要任何一边做后台运行的线程:
WebClient.await竟返回了的async方法,使请求线程.该请求线程返回到线程池 - 留下0(零)个线程为此请求提供服务.async方法将在请求线程上恢复.该请求线程仅用于编写实际响应.这是最佳的线程解决方案(因为需要请求线程来编写响应).
原始示例也最佳地使用线程 - 就线程而言,它与async基于代码的线程相同.但IMO的async代码更容易阅读.
如果您想了解更多信息async,我的博客上有一个简介.
我一直在通过互联网寻找信息几天.让我总结一下我迄今发现的情况:
ASP.NET ThreadPool事实
正如Andres所说:当async/await不会消耗额外的ThreadPool线程时?仅在您使用BCL异步方法的情况下.使用IOCP线程执行IO绑定操作.
安德烈斯继续... 如果你想异步执行一些同步代码或你自己的库代码,这些代码可能会使用一个额外的线程池线程,除非你明确的使用IOCP线程池或您自己的线程池.
但据我所知,你不能选择whetever要使用IOCP线程,并作出正确的执行线程池是不值得的.我怀疑有人做了一个已经存在的更好的.
ASP.NET使用公共语言运行时(CLR)线程池中的线程来处理请求.只要线程池中有可用的线程,ASP.NET就可以轻松调度传入的请求.
异步delegates使用ThreadPool中的线程.
什么时候开始考虑实现异步执行?
当您的应用程序执行相对冗长的I/O操作(数据库查询,Web服务调用和其他I/O操作)时
如果你想做I/O工作,那么你应该使用I/O线程(I/O完成端口),特别是你应该使用你正在使用的任何库类支持的异步回调.他们的名字以单词Begin和开头End.
如果请求的计算成本低廉,那么并行性可能是一种不必要的开销.
如果传入的请求速率高,则增加了更多并行可能会产生一些好处,实际上可能会降低性能,因为工作的传入速率可以足够高,以保持CPU的繁忙.
我应该创建新线程吗?
避免创建新线程,就像避免瘟疫一样.
如果您实际上排队了足够的工作项以防止ASP.NET处理进一步的请求,那么您应该将线程池挨饿!如果你是在同一时间运行字面上数百个CPU密集型操作的,它会做什么好事,有另一个工作者线程来服务ASP.NET请求,当机器已经超负荷.
和TPL?
TPL可以适应使用流程中的可用资源.如果服务器已经加载,则TPL可以使用少至一个工作程序并进行前进.如果服务器大部分是免费的,那么他们可以增长使用ThreadPool可以节省的工作量.
任务使用线程池线程来执行.
参考
| 归档时间: |
|
| 查看次数: |
9869 次 |
| 最近记录: |