在Asp.Net中使用“ThreadPool.QueueUserWorkItem”创建一个巨大的pdf报告,我的要求是报告必须异步创建,我不想等待响应。我计划通过以下代码实现它
protected void Button1_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(report => CreateReport());
}
public void CreateReport()
{
//This method will take 30 seconds to finish it work
}
我的问题是ThreadPool.QueueUserWorkItem将从Asp.Net工作进程或某个系统线程创建一个新线程。这是一个好方法吗?我可能有100个并发用户访问该网页。
答案 0 :(得分:3)
QueueUserWorkItem()
方法使用进程的ThreadPool,它自动管理多个工作线程。为这些线程分配一个任务,将它们运行完成,然后返回到ThreadPool以供重用。
由于这是在ASP.NET中托管的,因此ThreadPool将属于ASP.NET进程。
ThreadPool非常适合这类工作;作为旋转专用线程的替代方案相对昂贵。但是,您还应该考虑ThreadPool的以下限制:
ThreadPool由.NET的其他方面使用,并提供有限数量的线程。如果您过度使用它,您的任务可能会被阻止等待其他人完成。这在可伸缩性方面尤其令人担忧 - 但它不应该阻止您使用ThreadPool,除非您有理由相信它会成为瓶颈。
必须仔细管理ThreadPool任务,以确保返回它们以供重用。未处理的异常或从后台线程返回将基本上“泄漏”该线程并防止它被重用。在这些情况下,ThreadPool可能会有效地丢失它的线程并导致严重的减速或停止进程。
您分配给ThreadPool的任务应该是短暂的。如果您的处理过程密集,那么最好为其提供专用线程。
所有这些主题都涉及ThreadPool用于小任务的简单概念,以及通过重用来为消费代码提供成本节约的线程。您的场景听起来像是使用ThreadPool的合理案例 - 但是您需要仔细编写它,并确保运行实际的负载测试以确定它是否是最佳方法。
答案 1 :(得分:2)
线程池将根据需要管理活动线程的数量。线程完成任务后,它将继续执行下一个排队任务。使用线程池通常是处理后台处理的好方法。
在ASP.NET应用程序中运行时,有几件事需要注意:
在您的情况下,更好的方法可能是使用REST / JSON绑定的WCF服务,该绑定由客户端网页上的AJAX代码调用,以执行繁重的工作。这样您就可以将流程和结果报告给用户。
答案 2 :(得分:1)
除了Anders Abel已经提出的内容,我完全同意,你应该考虑ASP.NET也使用线程池来响应请求,所以如果你长时间运行这样的工作就用了一个线程池线程,它从技术上窃取ASP.NET无论如何都可以用来满足其他请求的资源。
如果您问我如何最好地构建它,我会说您使用MSMQ传输上的单向消息传递将工作分派给WCF服务。这样,它可以快速分派,对故障具有弹性,并且可以更严格地控制WCF端上的请求处理,因为消息将仅位于等待处理的队列上。因此,如果您的服务器一次只能创建10个PDF,您只需将WCF服务的maxConcurrentCalls设置为10,它一次只能从队列中拉出最多10条消息。此外,如果您的服务关闭,当它启动时,它将再次开始处理。