如何知道谁杀了我的线程

时间:2010-04-20 14:26:47

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

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

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

至于线程,我可以断言它在死亡前至少执行了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。在烛台的客厅里,不是Lady Goldent:)

15 个答案:

答案 0 :(得分:20)

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

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

答案 1 :(得分:13)

您的主题可能只是抛出异常。尝试在DoSomethingForALongLongTime周围放置一个try / catch块,看看它是什么。


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

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

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

答案 2 :(得分:5)

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

  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(请参阅!help对于其他sos命令)
  6. 如果您从其他线程中获得大量噪音,请在断开后继续编写windbg,如果它不是您关心的线程ID。

    修改:如果您认为该流程已在流程中终止,您还可以在TerminateThreadbp kernel32!TerminateThread)和ExitThread上设置断点(bp kernel32!ExitThread)抓住凶手的堆栈。

答案 3 :(得分:4)

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

  • 可能会抛出异常吗?您是否尝试在DoSomethingForALongLongTime()调用周围进行try / catch?
  • 是否有任何正常退出的点?尝试记录一下。
  • 您是否在调试器内外获得相同的行为?调试器中的输出窗口是否提供任何提示?

<强>更新

你说:

  

此主题由网站创建   服务器,继续运行

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

答案 4 :(得分:4)

您的编辑会显示答案:

  

这是管家网络服务器。

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

修改
要快速修复,最好的机会是设置worker.IsBackground = false;,因为当前设置为true允许系统终止父线程,而不用等待你的bgw。

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

答案 5 :(得分:3)

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

答案 6 :(得分:3)

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

答案 7 :(得分:2)

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

答案 8 :(得分:2)

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

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

希望这有帮助。

答案 9 :(得分:2)

您可以尝试在 web.config 中增加 configuration \ system.web \ httpRuntime executionTimeout 值(默认值为110秒in .NET 4.0和90对应于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();而不是使用线程的进程。

答案 10 :(得分:2)

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

答案 11 :(得分:1)

它可能会抛出各种无法捕获的异常之一,包括 Stack Overflow Out of Memory 。这些是追踪的最难例外。

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

答案 12 :(得分:1)

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

答案 13 :(得分:1)

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

答案 14 :(得分:1)

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

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