我正在构建一个多线程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页面然后重新打开它,我想我会有两个运行的每个线程的实例。那是对的吗?如果是这样,我如何检查这些线程是否已经在运行,以便我不创建它们的新实例?
希望这是有道理的!在此先感谢您的帮助。这是我的代码。
Start.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();
}
}
}
}
答案 0 :(得分:2)
我正在构建一个多线程ASP.NET应用程序。我是新来的 编写多线程应用程序。我有一个主类产生一个数字 在使用应用程序时运行的线程。
NOOOO。你不应该这样做。从ASP.NET中生成一个新线程是一种用脚射击自己的公平方法。为什么?因为每个新请求通常从ASP.NET线程池获取专用线程。您可以获得的线程数量非常有限(因此逻辑并发请求的数量)。如果一个请求产生另一个手动线程 - 会发生奇怪的事情,从内存泄漏,死锁开始,最终导致应用程序或Web服务器崩溃。
处理完请求后,您的服务器应该完全忘记用户。
相反,请考虑不同的方法。维持国家:
恢复每个新请求的状态并比较时间。
答案 1 :(得分:1)
我不喜欢你的设计,但这是一个单独的问题。我将用您当前的设计解决您当前的问题...
在Start()
函数中,如果线程不为null,则将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)与您的页面进行交互的后台工作。