如何知道谁杀了我的线程

我有一个只是放逐的线程..我想知道是谁杀了我的线程,为什么。

它发生在我的线程被操作系统杀死,但我想确认这一点,如果可能的话,知道为什么它会杀了它。

至于线程,我可以断言它在死亡前至少有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(); } 

编辑:寻址答案

  • Try / Catch可能的例外情况:
    它实施了,它什么都没有抓住:(
  • 主线死亡:
    该线程由Web服务器创建,该服务器继续运行
  • 工作完成:
    工作没有完成,因为它最终会影响数据库,我可以在线程死亡时检查它是否完成。

想到这些事情就把我带到了这个问题,谁杀了我的线程?

PS。 在烛台的客厅里,不是Lady Goldent 🙂

各种各样的人(包括我自己, 在这里 )指出,在IIS中托管一个长期运行的线程是一个坏主意。 您的线程将在IIS“工作进程”中运行。 这些进程由IIS定期终止(回收),这将导致您的线程死亡。

我建议你尝试关闭IIS工作进程回收,看看是否有所作为。 您可以在此处找到更多信息。

你的线程可能只是抛出exception。 尝试在DoSomethingForALongLongTime周围放置一个try / catch块,看看它拿起了什么。


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

这很糟糕,因为只要请求持续,这些事情就会持续下去。 一旦请求结束,它们就会变得无效,至少可以说。

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

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

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

如果你从其他线程中获得很多噪音,如果它不是你关心的线程ID,脚本windbg会在断开后继续。

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

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

  • 可能会抛出exception吗? 您是否尝试过围绕DoSomethingForALongLongTime()调用尝试/捕获?
  • 它有正常退出的点吗? 尝试对它们进行一些登录。
  • 您是否在调试器内外获得相同的行为? 调试器中的输出窗口是否提供任何提示?

UPDATE

你说:

该线程由Web服务器创建,该服务器继续运行

如果线程在asp.net中运行,则可能是当asp.net工作进程回收时线程被杀死,它将定期执行。 您可以尝试关闭工作流程回收,看看是否有任何区别。

您的编辑显示答案:

这是管家网络服务器。

你是如何主持这些线程的? Web服务器环境并非完全用于托管长期生存进程。 事实上,它可能被配置为每隔40分钟停止一次失控的网站?

编辑:
要快速修复,最好的机会是设置worker.IsBackground = false; 因为你当前的设置为true允许系统杀死没有等待你的bgw的父线程。

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

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

只有前景线程runnnig才能运行后台线程。

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

如果检查exception没有显示任何有用的内容,请获取您的线程代码以在关键点写入日志文件。 然后,您将能够确切地看到它何时停止工作,并希望为什么。

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

  • 如果您的线程托管在IIS中,则该线程可能会被回收的应用程序池进程终止。 服务器可能会继续运行,但会停止托管您项目的进程,直到新请求再次触发所有内容。
  • 如果你的线程托管在一个可执行文件中,那么杀死它的唯一方法就是自己杀死线程,在线程中抛出exception或终止主机进程

希望这可以帮助。

您可以尝试在web.config中增加configuration \ system.web \ httpRuntime的 executionTimeout值(.NET 4.0中的默认值为110秒,而对应于http://msdn.microsoft.com/en-us/library/的 90 in) e1f13641.aspx )。 您可以尝试动态更改它Server.ScriptTimeout = 300(请参阅http://www.beansoftware.com/ASP.NET-Tutorials/Long-Operations.aspx )。 这个参数不会有帮助,那么我认为你有一个问题,比如从IIS回收线程。 如何查看此参数的默认值远小于线程的典型实时时间。 我认为,你的问题有另一种性质,但要确定……

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

还有一点建议。 你可以在调用SomethingForALongLongTime();之后插入一行代码吗SomethingForALongLongTime(); 可以肯定的是, SomethingForALongLongTime没有例外而没有结束?

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

当您调用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); } } 

它可能会抛出各种不可捕获的exception之一,包括Stack OverflowOut of Memory 。 这些是追踪的最难例外。

这个线程运行时内存消耗是什么样的? 你可以在它上面使用内存分析器来查看它是否失控? 你能在内循环中添加一些日志记录吗? 如果你有一个递归方法,添加一个计数器并抛出一个例外,如果它递归不可能的次数。 您是否正在使用可能导致大对象堆碎片的大对象(即使您没有真正出局也会导致内存不足错误)。

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

使用AsyncTasks在asp.net中实现长期运行

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

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