代码之家  ›  专栏  ›  技术社区  ›  char m

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

  •  1
  • char m  · 技术社区  · 15 年前

    在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相同的锁保护部分调用。这两个调用都在具有catch块的try-bolck中。

    现在我的问题是 1。如果loadallsystemdata引发异常,当在方法刷新中从非线程池线程调用它时,会发生什么?没人能抓住它。

    1. 做了1000次会怎么样?这些异常是否存储在某个地方,从而使系统受到压力,最终由于内存耗尽或其他原因而崩溃?

    2. 是否有好的解决方案可以在创建线程池线程中不等待创建线程完成就捕获它们?

    谢谢!-马蒂

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