在ASP.NET Web应用程序中,工作线程创建一个非线程池线程,如下所示:
private static bool _refreshInProcess = false;
public delegate void Refresher();
private static Thread _refresher;
private static void CreateAndStartRefreshThread(Refresher refresh)
{
_refresher = new Thread(new ThreadStart(refresh));
_refresher.Start();
}
private static void Refresh()
{
LoadAllSystemData();
}
static public void CheckStatus()
{
DateTime timeStamp = DateTime.Now;
TimeSpan span = timeStamp.Subtract(_cacheTimeStamp);
if (span.Hours >= 24)
{
if (Monitor.TryEnter(_cacheLock))
{
try
{
if (!_refreshInProcess)
{
_refreshInProcess = true;
CreateAndStartRefreshThread(Refresh);
}
}
finally
{
Monitor.Exit(_cacheLock);
}
}
}
}
static public void LoadAllSystemData()
{
try
{
if (!Database.Connected)
{
if (!OpenDatabase())
throw new Exception("Unable to (re)connect to database");
}
SystemData newData = new SystemData();
LoadTables(ref newData);
LoadClasses(ref newData);
LoadAllSysDescrs(ref newData);
_allData = newData;
_cacheTimeStamp = DateTime.Now; // only place where timestamp is updtd
}
finally
{
_refreshInProcess = false;
}
}
和LoadAllSystemData也在与CheckStatus相同的锁定保护部分的其他地方调用 . 两次调用都在他们的try-bolcks中,也有catch-block .
现在我的问题是1.如果LoadAllSystemData抛出异常,当它从方法Refresh中的非线程池线程调用时,会发生什么?没有人能 grab 它 .
-
完成1000次后会发生什么?这些异常是否存储在某处,从而对系统造成压力,并最终因内存耗尽而崩溃?
-
有没有好的解决方案来捕获它们而无需在创建线程池线程中等待创建的线程完成?
非常感谢! -Matti
1 回答
如果在后台非线程池线程中引发异常并且最终它没有被任何catch块处理,则它会向上传播直到它到达堆栈的开头 . 然后线程完成其执行 - 异常不存储在任何地方 . 然后删除线程以及包含对异常的引用的堆栈 .
.NET中的异常抛出是昂贵的,所以如果你预计它会发生1000次,可能它不是一个例外,而只是你的应用程序流的一部分,你不应该在这里引发异常 .
如果要从后台活动中捕获异常,可以使用委托的BeginInvoke / EndInvoke方法作为选项 . 如果后台操作中有任何异常,它将在EndInvoke调用中传递 .