从创建的非线程池线程的ASP.NET异常会发生什么?

时间:2009-12-02 15:04:59

标签: c# asp.net multithreading exception-handling

在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中从非线程池线程调用它时,会发生什么?没有人能抓住它。

  1. 完成1000次后会发生什么?这些异常是否存储在某个地方,从而给系统带来压力,并最终因内存耗尽而崩溃?

  2. 有没有很好的解决方案来捕获它们而无需在创建线程池线程中等待创建的线程完成?

  3. 非常感谢! -Matti

1 个答案:

答案 0 :(得分:1)

  1. 如果在后台非线程池线程中引发异常并且最终它没有被任何catch块处理,则它会向上传播直到它到达堆栈的开头。然后线程完成其执行 - 异常不存储在任何地方。然后删除线程以及包含对异常的引用的堆栈。
  2. 在.NET中,异常抛出是很昂贵的,所以如果你预计它会发生1000次,可能它不是一个例外,而只是你应用程序流的一部分,你不应该在这里引发异常。
  3. 如果要从后台活动中捕获异常,可以使用委托的BeginInvoke / EndInvoke方法作为选项。如果后台操作中有任何异常,它将在EndInvoke调用中传递。