c# - 在 Application_Start 上启动长时间运行的线程时的潜在陷阱

标签 c# asp.net .net multithreading iis

我希望将这篇文章塑造成一个合法的 StackOverflow 问题,因为我真的很想深入了解这种情况,但我绝对可以看看它是否过于本地化或被视为“意见”。

这是我的场景:当我加载我的网络应用程序时,我从数据库中加载了一大堆数据并将其缓存。问题是,这个过程大约需要 10-15 秒,并且会在 Web 服务器首次启动时造成延迟。这在开发时有点烦人,当我在生产环境中启动 Web 服务器时也会导致一些问题(因为这是一个新站点,我经常在发现小错误时立即修复它们,或者修改 IIS 设置)。

我想知道 - 我是否可以在应用程序启动时将这项工作转移到一个新线程中,并在其他用户使用该网站时在后台继续进行?显然,某些功能在网站加载后大约 10-15 秒内无法使用,但我可以处理该情况或阻止直到数据可用。起初,我认为不会。如果请求结束,Web 服务器将终止这些线程,或者阻塞直到这些线程完成。我决定编写一个小测试应用程序来测试这个理论:

public class Global : System.Web.HttpApplication
{
   void Application_Start(object sender, EventArgs e)
   {
      Thread thread = new Thread(LoadData);
      thread.Start();
   }

   private void LoadData()
   {
      for (int i = 0; i < 100; i++)
      {
         Trace.WriteLine("Counter: " + i.ToString());
         Thread.Sleep(1000);
      }
   }
}

当应用程序启动时,我启动一个新线程,并让它计数到 100。令我惊讶的是,我立即进入主页,在我的 Visual Studio 调试输出窗口中,我可以看到递增的数字计数向上。我真的很惊讶这能奏效。

我的问题:

首先,这样做有什么陷阱吗?它是在自找麻烦吗?有什么东西会爆炸吗?这种行为是否会在 Web 服务器或 IIS 版本之间发生变化,因为它们可能使用不同的线程模型?我正在寻找对此设计的总体反馈。

最佳答案

tl;dr:您所做的可能没问题,并且是处理这种情况的常用方法。

线程肯定有问题。并不是说在这种情况下你不应该使用它们,但是确保你理解它们是明智的。滥用一个古老的模因:“程序员经常会看到并发问题,并通过使用另一个线程来解决它。现在他们有两个问题。”

如果您的线程是后台线程(这意味着如果线程仍在运行,它不应阻止您的站点关闭),请确保设置了 IsBackground 属性。更好的是,使用 BackgroundWorker .

在初始化线程完成之前,您的网站的可用性如何?是否有任何真正的理由在初始化时显示界面?

我在直接使用线程进行并发方面走了一个完整的圈子——从害怕它们,到认为我理解它们并拥抱它们,再到认为我理解它们并害怕它们。现在,当我遇到要解决的并发/异步问题时,我通常会尝试创建一个由多个相互通信的并发(但单线程)进程组成的架构。很多事情都以这种方式变得更简单,而且我已经取得了很大的成功。

在您当前的情况下,如果您可以确保在线程准备好资源之前不访问该线程正在准备的资源,那么使用后台线程处理数据库负载可能就足够安全了。但是,(如果您可以针对 .Net 4.0),更好的方法是利用 Task Async library - 也就是说,将您的例程编写为异步的,并返回 T 的 Task 而不是 T 本身。如果处理得当,这可以让您的网站响应用户,即使在单线程环境中,甚至在它仍在后台加载资源时也是如此。

关于c# - 在 Application_Start 上启动长时间运行的线程时的潜在陷阱,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12923616/

相关文章:

c# - c++:使用类型作为 map /字典的键?

c# - 泛型方法中的条件类型

c# - 升级到 .Net 4.5 会导致程序集失败?

c# - WPF FlowDocument - 绝对字符位置

c# - 在一定时间后没有收到数据时断开套接字

c# - 如何在 global.asax 中设置默认的 cookie 值?

c# - 超链接、按钮以及打开新浏览器窗口的任何内容的列表

c# - 在 asp.net 中组装

c# - ASP.NET - 能够将 CSV/excel 导出到多个工作表?

.net - WebBrowser(WPF 和 WinForms 控件)和 JSON 对象 - JSON 未定义