【问题标题】:ThreadPool.QueueUserWorkItem uses ASP.NetThreadPool.QueueUserWorkItem 使用 ASP.Net
【发布时间】:2011-08-06 05:49:24
【问题描述】:

在 Asp.Net 中使用“ThreadPool.QueueUserWorkItem”创建一个巨大的 pdf 报告 iam,我的要求是必须异步创建报告,我不想等待响应。我打算通过下面的代码来实现它

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

【问题讨论】:

    标签: c# .net asp.net


    【解决方案1】:

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

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

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

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

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

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

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

    【讨论】:

      【解决方案2】:

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

      在 ASP.NET 应用程序中运行时,需要注意以下几点:

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

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

      【讨论】:

      • 感谢您的回复,是否使用 Asp.Net 线程/系统线程?
      • 线程池在内部使用系统线程,但使用池的优点是您不必关心它是如何完成的。线程管理在黑盒中提供。我假设 WCF 在内部使用线程池来处理请求,但它在那里是一样的——你不必关心。只需让框架为您处理复杂的线程即可。
      【解决方案3】:

      除了 Anders Abel 已经提出的(我完全同意)之外,您应该考虑到 ASP.NET 也使用线程池来响应请求,所以如果您长时间运行这样的工作会占用一个线程池线程,从技术上讲,它是从 ASP.NET 能够用来满足其他请求的资源中窃取。

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

      【讨论】:

      • 我同意 WCF 可能是最好的方法,但要正确了解技术事实...“@anders Abel”回复 Threadpool 使用系统线程(不是来自 ASP.Net 资源)? ,但是在您提到的关于 asp.net 的回复中使用相同的线程池..
      猜你喜欢
      • 2011-01-13
      • 2022-06-10
      • 2010-11-22
      • 1970-01-01
      • 1970-01-01
      • 2010-12-31
      • 1970-01-01
      • 2011-09-05
      • 2011-03-04
      相关资源
      最近更新 更多