1

我正在构建一个多线程 ASP.NET 应用程序。我是编写多线程应用程序的新手。我有一个主类,它产生许多在使用应用程序时运行的线程。该应用程序有一个主要的 HTML 页面。当 HTML 页面第一次打开时,它调用 MyController.Start() 方法来创建线程并让它们运行。然后 HTML 页面有一个 Javascript 例程,它不断地轮询我的应用程序中的 ASPX 页面(每 2 秒)以获取数据并显示它。有一个我称为“MyController”的主类,它是应用程序的核心。它有一个名为 Canceled 的本地布尔变量,该变量设置为 false。MyController 产生所有子线程。每个子线程都有一个循环,只要 Canceled = false 就会继续执行。正在运行的线程之一用作监视器,以确保 HTML 页面仍处于启动状态并进行轮询。如果该线程注意到自上次轮询 HTML 页面以来已过 30 秒,则它将 Canceled 变量更改为 true。然后所有线程一个接一个地完成运行并优雅地关闭。

我需要能够处理用户关闭浏览器然后在 30 秒到期之前重新打开它的情况。我觉得我没有完全理解创建和启动的线程与 MyController 实例之间的关系。一旦线程被创建并启动,它们是否会独立于其他任何东西运行?我有一个名为 App 的主要静态类,用于从应用程序的任何位置轻松访问控制器。我现在编码的方式我认为每次加载 HTML 页面时我都会创建新线程。因此,如果用户要关闭 HTML 页面然后重新打开它,我想我会运行每个线程的两个实例。那是对的吗?如果是这样,我如何检查这些线程是否已经在运行,以便我不'

希望这是有道理的!提前感谢您的帮助。这是我的代码。

启动.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
  if(App._myController == null)
  {
    App._myController = new MyController();
  }
  App._myController.Start();
}

库代码

public class App
{
  public static MyController _myController {get;set;}
  static App()
  {
    _myController = new MyController();
  }
}

public class MyController
{
  public bool Cancelled {get;set;}
  private object SyncLock = new object();
  Thread _thread1;
  Thread _thread2;
  Thread _thread3;

  public void Start()
  {
    this.Cancelled = false;
    _thread1 = new Thread(Worker1);
    _thread1.Start();

    _thread2 = new Thread(Worker2);
    _thread2.Start();

    _threadMonitor = new Thread(Monitor);
    _threadMonitor.Start();
  }

  public void Stop()
  {
    lock(this.SyncLock)
    {
      this.Cancelled = true;
    }
  }

  private void Worker1()
  {
    while(!Cancelled)
    {
      ..do some stuff..
    }
  }

  private void Worker2()
  {
    while(!Cancelled)
    {
      ..do some stuff..
    }
  }

  private void Monitor()
  {
    while(!Cancelled)
    {
      ..check database to see when last poll was
      ..if last poll is greater than 30 seconds ago
      {
        this.Stop();
      }
    }
  }

}
4

2 回答 2

2

我正在构建一个多线程 ASP.NET 应用程序。我是编写多线程应用程序的新手。我有一个主类,它产生许多在使用应用程序时运行的线程。

不。你不应该那样做。从 ASP.NET 生成一个新线程是一个公平的方法,可以让你自食其果。为什么?因为每个新请求通常都会从 ASP.NET 线程池中获取一个专用线程。您可以获得的线程数量非常有限(因此逻辑并发请求的数量)。如果一个请求产生另一个手动线程 - 奇怪的事情会发生,从内存泄漏、死锁开始,最终导致你的应用程序或 Web 服务器崩溃。

处理请求后,您的服务器应该完全忘记用户。

相反,考虑不同的方法。保持状态:

  • 数据库
  • 用户 cookie
  • html隐藏字段
  • 由 ASP.NET 本身序列化/反序列化的 ASP.NET 容器

恢复新的每个请求的状态并比较时间。

于 2013-01-09T16:06:35.267 回答
1

我不喜欢你的设计,但这是一个单独的问题。我将用您当前的设计解决您当前的问题...

从您的Start()函数中,如果线程不为空​​,请将线程设置Cancelled为 true Join(),然后继续使用现有功能。

  public void Start()
  {
    this.Cancelled = true;

    if (_thread1 != null) _thread1.Join();
    // repeat for other threads

    this.Cancelled = false;
    _thread1 = new Thread(Worker1);
    _thread1.Start();

    _thread2 = new Thread(Worker2);
    _thread2.Start();

    _threadMonitor = new Thread(Monitor);
    _threadMonitor.Start();
  }

至于更好的方法,也许是一个服务来做后台工作,使用 WCF(也许使用 REST)与您的页面交互。

于 2013-01-09T16:07:16.620 回答