在Application_Start上启动长时间运行的线程时可能存在的缺陷

时间:2012-10-16 21:22:08

标签: c# asp.net .net multithreading iis

我希望将这篇文章塑造成一个合法的StackOverflow问题,因为我非常希望对这种情况有充分的理解,但我可以肯定地看到它是否过于本地化或被视为“意见”。

这是我的方案:当我加载我的Web应用程序时,我从数据库加载一大堆数据并缓存它。问题是,此过程大约需要10-15秒,并在Web服务器首次启动时产生延迟。这在开发时有点烦人,当我在生产环境中反弹Web服务器时也会引起一些问题(因为这是一个新站点,我经常在找到它们时修复小错误,或者使用IIS设置)。< / p>

我想知道 - 我可以在应用程序启动时将此工作卸载到新线程中,并在其他用户使用该网站时在后台进行此操作吗?显然,当网站加载时,某些功能在大约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版本之间发生变化,因为它们可能使用不同的线程模型吗?我正在寻找有关此设计的整体反馈。

2 个答案:

答案 0 :(得分:2)

tl; dr:你正在做的事情可能很好,也是处理这种情况的常用方法。

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

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

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

我已经全力以赴地直接使用线程来实现并发 - 从害怕它们到思考我理解它们并拥抱它们,认为我理解它们并且害怕它们。现在,当我有一个我想要解决的并发/异步问题时,我通常会尝试创建一个由多个,相互通信,并发(但是单线程)进程组成的体系结构。很多事情都变得越来越简单,我已经取得了很大的成功。

在目前的情况下,如果您可以确保在准备好之前没有访问线程正在准备的资源,那么使用后台线程来处理数据库负载可能是足够安全的。但是,(如果你可以定位.Net 4.0),一个更好的方法来做你想要的就是利用Task Async库 - 也就是说,编写你的例程是异步的,并返回一个T的任务而不是T本身。如果操作正确,这可以让您的站点响应用户,即使在单线程环境中,甚至在后台仍在加载资源时也是如此。

答案 1 :(得分:1)

当你去使用缓存中不存在的东西时,你会发现这个问题。

我同意Drew就像BackGroundWorker一样。

网站需要有两种模式,禁用的功能取决于缓存 BackGroundWorker完成后,打开所有功能 用户不喜欢点击按钮被告知未准备好稍后再试。