来自创建的非线程池线程的 ASP.NET 异常会发生啥?

Posted

技术标签:

【中文标题】来自创建的非线程池线程的 ASP.NET 异常会发生啥?【英文标题】:what happens to ASP.NET exceptions from created non-threadpool thread?来自创建的非线程池线程的 ASP.NET 异常会发生什么? 【发布时间】:2010-12-22 10:51:19 【问题描述】:

在 ASP.NET Web 应用程序中,工作线程创建一个非线程池线程,如下所示:

私有静态 bool _refreshInProcess = false; 公共代表无效 Refresher(); 私有静态线程_refresher; 私有静态无效 CreateAndStartRefreshThread(刷新刷新) _refresher = 新线程(新线程开始(刷新)); _refresher.Start(); 私有静态无效刷新() 加载所有系统数据(); 静态公共无效检查状态() 日期时间时间戳 = 日期时间。现在; TimeSpan span = timeStamp.Subtract(_cacheTimeStamp); if (span.Hours >= 24) if (Monitor.TryEnter(_cacheLock)) 尝试 如果(!_refreshInProcess) _refreshInProcess = true; CreateAndStartRefreshThread(Refresh); 最后 Monitor.Exit(_cacheLock); 静态公共无效LoadAllSystemData() 尝试 if (!Database.Connected) 如果(!OpenDatabase()) throw new Exception("无法(重新)连接到数据库"); 系统数据 newData = new SystemData(); 加载表(参考新数据); 加载类(参考新数据); LoadAllSysDescrs(ref newData); _allData = 新数据; _cacheTimeStamp = DateTime.Now; // 只有时间戳是 updtd 的地方 最后 _refreshInProcess = false;

并且 LoadAllSystemData 也从与 CheckStatus 相同的锁保护部分调用。这两个调用都在它们的 try-bolcks 中,它们也有 catch-block。

现在我的问题是 1. 如果LoadAllSystemData抛出异常,在Refresh方法中从非线程池线程调用时,会发生什么?没有人能抓住它。

    执行 1000 次会发生什么?这些异常是否存储在某个地方,从而给系统带来压力并最终由于内存耗尽或其他原因导致系统崩溃?

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

非常感谢! -马蒂

【问题讨论】:

【参考方案1】:
    如果在后台非线程池线程中引发异常并且最终它没有被任何 catch 块处理,它会向上传播直到它到达堆栈的开头。然后线程完成其执行 - 异常不会存储在任何地方。然后删除线程及其包含对异常的引用的堆栈。 在 .NET 中抛出异常的成本很高,因此如果您预计它会发生 1000 次,那么它可能不是异常,而只是您的应用程序流程的一部分,您不应该在这里引发异常。 如果您想从后台活动中捕获异常,您可以选择使用委托的 BeginInvoke / EndInvoke 方法。如果后台操作出现异常,会在 EndInvoke 调用中传递。

【讨论】:

非常感谢!不想使用 Begin/EndInvoke,因为它使用线程池线程并且调用 EndInvoke 会停止创建线程的线程,直到它完成。 BeginInvoke 返回 IAsyncResult 对象。如果要防止请求线程阻塞,可以查询此对象的属性 IsCompleted。如果你想完全避免使用 ThreadPool,那么唯一的办法就是 Thread 类和手动线程同步

以上是关于来自创建的非线程池线程的 ASP.NET 异常会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 asp.net Core 中增加最大线程池限制

Java中的非阻塞异步IO

七天学会ASP.NET MVC ——线程问题异常处理自定义URL

七天学会ASP.NET MVC ——线程问题异常处理自定义URL

异步Action之AsyncController

ASP.NET MVC中使用异步控制器