4

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

这是我的场景:当我加载我的 Web 应用程序时,我从数据库中加载了一大堆数据并将其缓存。问题是,这个过程大约需要 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 版本之间发生变化,因为它们可能使用不同的线程模型?我正在寻找有关此设计的总体反馈。

4

2 回答 2

2

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

线程肯定有问题。并不是说您不应该在这种情况下使用它们,但明智的做法是确保您理解它们。滥用一句老梗:“程序员经常会看到一个并发问题,然后用另一个线程解决它。现在他们有两个问题。”

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

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

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

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

于 2012-10-16T21:32:53.323 回答
1

问题是当你去使用缓存中不存在的东西时。

我同意 Drew 的观点,就像一个 BackGroundWorker。

The site needs to have two modes were features are disabled that depend on the cache.
When the BackGroundWorker is complete then turn on all the features.
Users do no like clicking a button to be told not ready try again later.

于 2012-10-16T21:42:28.277 回答