【问题标题】:How to know who kills my threads如何知道谁杀死了我的线程
【发布时间】:2010-04-20 14:26:47
【问题描述】:

我有一个正在驱逐的线程.. 我想知道谁在杀死我的线程以及为什么。

我突然想到我的线程被操作系统杀死了,但我想确认一下,如果可能的话,我想知道它为什么会杀死它。

至于线程,我可以断言它在死亡前至少有 40 分钟的执行时间,但它在 5 分钟左右突然死亡。

public void RunWorker()
{
    Thread worker = new Thread(delegate()
    {
        try
        {
            DoSomethingForALongLongTime();
        }
        catch(Exception e)
        {
           //Nothing is never logged :(
           LogException(e);
           throw e;
        }
    });

    worker.IsBackground = true;
    worker.SetApartmentState(System.Threading.ApartmentState.STA);
    worker.Start();
}

编辑:解决答案

  • 尝试/捕获可能的异常:
    它已实现,但什么也没捕获:(
  • 主线程死亡:
    该线程由 Web 服务器创建,并继续运行
  • 工作完成:
    工作没有完成,因为它最终影响到数据库,我可以在线程死亡时检查它是否完成。

想到这些,我想到了这个问题,谁在扼杀我的线程??

ps。不是戈登夫人拿着蜡烛在客厅里 :)

【问题讨论】:

  • 线程被nixed时是否发生异常,如果是,它说明了什么?你确定线程不会简单地结束,这也可以解释它的消失。
  • 这可能会成为 CSI 的精彩剧集。 ;)
  • 如果是 ASP.NET 和/或 IIS,请添加这些标签
  • 两个 cmets:* 你说“可能的”例外。也许您遗漏了一些东西,所以我建议您捕获异常(为了调试)。 * 在线程的正常退出点放置断点。看看能不能打。这两项措施肯定会排除两种可能的情况。
  • 上校在拿着管子的公寓里惊慌失措。

标签: c# .net asp.net multithreading iis-5


【解决方案1】:

很多人(包括我自己,here)指出在 IIS 中托管一个长时间运行的线程是个坏主意。您的线程将在 IIS“工作进程”中运行。 IIS 会定期终止(回收)这些进程,这将导致您的线程终止。

我建议您尝试关闭 IIS 工作进程回收,看看是否会有所不同。您可以找到更多信息here

【讨论】:

  • 这看起来很有希望;它适合所有症状。但令我惊讶的是,IIS 可以将所有线程状态迁移到子进程,而他的 DoStuffForLongTime() 函数甚至都不知道。是共享内存吗?
  • 因为这是后台线程,它不必永远运行。一旦主机的最后一个前台线程结束,其他一切都会向南......我不知道你是否可以欺骗 IIS,但我只需更改为前台并进行测试。
【解决方案2】:

您的线程可能只是抛出了一个异常。尝试在 DoSomethingForALongLongTime 周围放置一个 try/catch 块,看看它会收到什么。


更新:我之前没有注意到您是从网络服务器启动的。这可能是一个非常糟糕的主意。特别是,单独的线程是否使用从HttpContext.Current 派生的任何信息?这将包括RequestResponseSession 等,以及页面中的任何信息。

这很糟糕,因为这些事情只会在请求持续的时间内持续存在。一旦请求结束,它们就会变得无效,至少可以这么说。

如果您需要从 Web 应用程序或 Web 服务中启动一个长时间运行的线程,那么您应该创建一个简单的 Windows 服务并在其中托管一个 WCF 服务。然后让网页将执行任务所需的所有信息发送到服务。该服务甚至可以使用 MSMQ 作为传输,这将确保即使服务繁忙也不会丢失任何消息。

【讨论】:

  • 也许您的线程做了一些完全非法的事情并且死于分段违规(这不会显示为异常)。您可能会创建一个信号处理程序,它会引发一个错误标志,然后您可以检查它。
  • @Justin:他正在运行 .NET。没有什么是完全非法的,也不会有例外。除非使用非托管代码,否则不会发生“段冲突”。
  • @Downvoter:如果你不说你为什么投反对票,那么没人会在乎你的想法。
【解决方案3】:

获取更多信息的潜在方法:附加调试器并在线程终止时中断。根据您的线程被终止的方式,这可能不起作用。

  1. 如果您还没有,请下载Debugging Tools for Windows
  2. 运行 windbg.exe,附加到您的进程
  3. 进入windbg,键入sxe et 以启用在线程退出时中断
  4. 当调试器中断时,检查系统、其他线程等的状态。
  5. 要获取托管堆栈,请加载 sos.dll(.loadby sos mscorsvr.loadby sos mscorwks.loadby sos clr 应该可以),然后运行 ​​!clrstack(有关其他 sos 命令,请参阅 !help

如果您从其他线程退出时收到很多噪音,如果它不是您关心的线程 ID,则脚本 windbg 在中断后继续。

编辑:如果您认为线程正在从您的进程中终止,您还可以在TerminateThread (bp kernel32!TerminateThread) 和ExitThread (bp kernel32!ExitThread) 上设置断点为抓住杀手的堆栈。

【讨论】:

  • 如果有人在您的线程上调用 Thread.Abort(),那么您可能会尝试捕获特殊异常 ThreadAbortException,以了解它。这不会告诉你是谁,但会告诉你什么时候。
【解决方案4】:

我不知道答案,但有一些想法:

  • 会引发异常吗?您是否尝试过在 DoSomethingForALongLongTime() 调用中添加 try/catch?
  • 是否有正常退出的点?尝试在它们上添加一些日志记录。
  • 在调试器中进出的行为是否相同?调试器中的输出窗口是否提供任何提示?

更新

你说:

本帖由网络创建 服务器,继续运行

如果线程在 asp.net 中运行,那么当 asp.net 工作进程回收时,线程可能会被杀死,它会定期执行此操作。您可以尝试关闭工作进程回收,看看是否有什么不同。

【讨论】:

【解决方案5】:

您的编辑揭示了答案:

这是 butler 网络服务器。

您究竟是如何托管这些线程的?网络服务器环境并不是专门为托管长期存在的进程而设计的。事实上,它可能被配置为每 40 分钟停止一次失控的网站?

编辑:
为了快速修复,您最好的机会是设置worker.IsBackground = false;,因为您当前的设置为 true 允许系统在不等待您的 bgw 的情况下终止父线程。

另一方面,在 ASP.NET 应用程序中使用 BackgroundWorker 没有什么意义,它适用于 WinForms 和 WPF。最好为此创建一个单独的线程,因为您正在更改一些线程属性。对于 ThreadPool (Bgw) 线程,不建议这样做。

【讨论】:

  • +1。 “LongLong”工作可能应该卸载到专用的应用程序/服务。
【解决方案6】:

进程可能正在终止。那就是worker.IsBackground = true;旨在做,当主线程退出时杀死你的线程。

【讨论】:

    【解决方案7】:

    只要有前台线程在运行,后台线程才会运行。

    一旦所有前台线程结束,任何仍在运行的后台线程都将中止。

    【讨论】:

      【解决方案8】:

      如果检查异常没有显示任何有用的信息,请让您的线程代码在关键点写入日志文件。然后,您将能够准确地看到它何时停止工作,并希望看到原因。

      【讨论】:

        【解决方案9】:

        一个简单的答案是:“凶手没有留下名片”;)

        • 如果您的线程托管在 IIS 中,则该线程可能被回收的应用程序池进程杀死。服务器可能会继续运行,但托管您的项目的进程会停止,直到新的请求再次启动所有内容。
        • 如果您的线程托管在可执行文件中,则可以杀死它的唯一方法是自己杀死线程、在线程中引发异常或终止宿主进程

        希望这会有所帮助。

        【讨论】:

          【解决方案10】:

          您可以尝试在 web.config 中增加 configuration\system.web\httpRuntimeexecutionTimeout 值(默认值为 110 秒) .NET 4.0 和 90 in 对应于 http://msdn.microsoft.com/en-us/library/e1f13641.aspx)。您可以尝试动态更改它 Server.ScriptTimeout = 300(请参阅http://www.beansoftware.com/ASP.NET-Tutorials/Long-Operations.aspx)。如果此参数无济于事,那么我认为您还有其他问题,例如从 IIS 回收线程。您如何查看此参数的默认值与线程的典型生存时间相比要少得多。我认为,您的问题具有另一种性质,但可以肯定...

          为什么要为线程设置单元状态?您在工作线程中使用了哪些 COM 对象?您是否有一个非托管代码可以完成大部分工作,您还可以在其中插入一些代码?我认为您应该了解更多关于SomethingForALongLongTime 的信息才能解决问题。

          还有一点建议。您能否在调用SomethingForALongLongTime(); 之后插入一行代码来确定SomethingForALongLongTime 不会无异常结束?

          更新:为了绝对确保您的线程不会被 IIS 杀死,您可以尝试创建一个执行 SomethingForALongLongTime(); 的进程,而不是使用线程。

          【讨论】:

            【解决方案11】:

            当您调用 RunWorker() 时,您可以将对线程的引用添加到列表中。一旦你检测到你的线程已经死亡,你可以检查线程的状态,也许它会揭示它是如何死亡的。或者,它可能还没有死,它只是在等待一些资源(比如与数据库的连接)。

            List runningThreads = ...
            public void RunWorker() {
                Thread worker = new Thread(delegate()
                ..
                runningThreads.add(worker);
                worker.Start();
            }
            
            public void checkThreads() {
             for (Thread t : runningThreads) {
               Console.WriteLine("ThreadState: {0}", t.ThreadState);
             }
            }
            

            【讨论】:

              【解决方案12】:

              它可能会引发各种无法捕获的异常,包括堆栈溢出内存不足。这些是最难追踪的例外情况。

              该线程运行时内存消耗情况如何?你可以使用内存分析器来查看它是否失控吗?您可以在内部循环中添加一些日志记录吗?如果您有递归方法,请添加一个计数器,如果递归次数不可能,则抛出异常。您是否使用了可能导致大对象堆碎片的大对象(即使您并没有真正出问题也会导致内存不足错误)。

              【讨论】:

                【解决方案13】:

                您应该使用大量调试日志来检测 DoSomethingForALongLongTime(),这样您就可以找出代码在什么位置停止执行。或者附加一个调试器并中断所有第一次机会异常。

                【讨论】:

                  【解决方案14】:

                  使用 AsyncTasks 实现您在 asp.net 中长期运行的工作

                  【讨论】:

                    【解决方案15】:

                    尝试使用应用域 UnhandledException 事件:http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

                    如果你错过了一些例外,它可能会给你一些信息

                    【讨论】:

                      猜你喜欢
                      • 2016-02-29
                      • 1970-01-01
                      • 2014-01-29
                      • 1970-01-01
                      • 2021-11-24
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2023-03-12
                      相关资源
                      最近更新 更多