ThreadPool.QueueUserWorkItem使用ASP.Net

时间:2011-08-05 21:34:45

标签: c# .net asp.net

在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个并发用户访问该网页。

3 个答案:

答案 0 :(得分:3)

QueueUserWorkItem()方法使用进程的ThreadPool,它自动管理多个工作线程。为这些线程分配一个任务,将它们运行完成,然后返回到ThreadPool以供重用。

由于这是在ASP.NET中托管的,因此ThreadPool将属于ASP.NET进程。

ThreadPool非常适合这类工作;作为旋转专用线程的替代方案相对昂贵。但是,您还应该考虑ThreadPool的以下限制:

  • ThreadPool由.NET的其他方面使用,并提供有限数量的线程。如果您过度使用它,您的任务可能会被阻止等待其他人完成。这在可伸缩性方面尤其令人担忧 - 但它不应该阻止您使用ThreadPool,除非您有理由相信它会成为瓶颈。

  • 必须仔细管理ThreadPool任务,以确保返回它们以供重用。未处理的异常或从后台线程返回将基本上“泄漏”该线程并防止它被重用。在这些情况下,ThreadPool可能会有效地丢失它的线程并导致严重的减速或停止进程。

  • 您分配给ThreadPool的任务应该是短暂的。如果您的处理过程密集,那么最好为其提供专用线程。

所有这些主题都涉及ThreadPool用于小任务的简单概念,以及通过重用来为消费代码提供成本节约的线程。您的场景听起来像是使用ThreadPool的合理案例 - 但是您需要仔细编写它,并确保运行实际的负载测试以确定它是否是最佳方法。

答案 1 :(得分:2)

线程池将根据需要管理活动线程的数量。线程完成任务后,它将继续执行下一个排队任务。使用线程池通常是处理后台处理的好方法。

在ASP.NET应用程序中运行时,有几件事需要注意:

  • ASP.NET应用程序可以出于各种原因进行回收。发生这种情况时,所有排队的工作项都会丢失。
  • 没有简单的方法向客户端Web浏览器发出操作已完成的信号。

在您的情况下,更好的方法可能是使用REST / JSON绑定的WCF服务,该绑定由客户端网页上的AJAX代码调用,以执行繁重的工作。这样您就可以将流程和结果报告给用户。

答案 2 :(得分:1)

除了Anders Abel已经提出的内容,我完全同意,你应该考虑ASP.NET也使用线程池来响应请求,所以如果你长时间运行这样的工作就用了一个线程池线程,它从技术上窃取ASP.NET无论如何都可以用来满足其他请求的资源。

如果您问我如何最好地构建它,我会说您使用MSMQ传输上的单向消息传递将工作分派给WCF服务。这样,它可以快速分派,对故障具有弹性,并且可以更严格地控​​制WCF端上的请求处理,因为消息将仅位于等待处理的队列上。因此,如果您的服务器一次只能创建10个PDF,您只需将WCF服务的maxConcurrentCalls设置为10,它一次只能从队列中拉出最多10条消息。此外,如果您的服务关闭,当它启动时,它将再次开始处理。