2009-08-14 158 views
10

我们运行一个C#控制台应用程序,该应用程序启动多个线程来完成工作。主要功能看起来是这样的:C#应用程序意外终止

try 
{ 
    DoWork(); 
} 
catch (Exception err) 
{ 
    Logging.Log("Exception " + err.ToString()); 
} 
Logging.Log("Finished"); 

DoWork()功能从数据库中读取新的就业机会,并生成线程来处理每一个工作项目。自上周以来,该应用程序开始神秘消失。它从进程列表中消失,事件日志中没有条目。日志文件显示工作到某一点:它不会记录异常或“完成”行。

关于C#应用程序如何消失的任何线索?

编辑:线程就像创建:

new Thread(SomeObj.StartFunc).Start(); 

有些人在没有线程运行出现失踪。

P.S.我们使用规则安装DebugDiag,以便在程序崩溃时创建崩溃转储。它在进程消失时没有创建任何转储文件。

+0

我们真的可以做什么是在DoWork的方法的一些更详细... – 2009-08-14 14:30:40

+0

是什么DoWork的创建和启动线程后怎么办?它会进入一个无限循环,立即退出,试图加入后台线程,或者是什么? – 2009-08-14 14:36:17

+0

它进入无限循环。后台线程更新他们的状态在用锁定语句保护的数组中。当一个线程完成时,它将从数组中删除它自己的条目。 – Andomar 2009-08-14 14:37:52

回答

9

什么是您用来运行控制台应用程序的身份?

你也可能要使用SetConsoleCtrlHandler捕捉到控制台事件。看看这blog了解更多详情。当控制台应用在服务帐户下运行时,我们遇到了类似问题,它偶尔会终止。我不确定这是否是你遇到的问题。让我知道我可以发布一些代码。

更新:看起来像你的情景类似于我们所经历的。在您的控制台事件处理程序中,您需要检查LogOff事件并返回true。看看这个KB文章

public static void inputHandler(ConsoleCtrl.ConsoleEvent consoleEvent) 
{ 
    if (ConsoleEvent == ConsoleCtrl.ConsoleEvent.CtrlLogOff) 
     return true; 
    return false; 
} 
+0

它由具有管理特权的帐户作为计划任务运行。我添加了处理程序并将其修改为记录事件,让它运行一段时间以查看它是否命中! – Andomar 2009-08-14 22:13:30

+2

我已经添加了日志记录,并且CtrlLogOff事件确实是导致计划任务退出的原因。问题解决了,尽管我们仍然想知道CtrlLogOff事件来自哪里! – Andomar 2009-09-04 13:21:24

+5

你是如何从void函数返回一个布尔值的? – Ruud 2012-12-15 11:50:28

9

您需要在每个线程工作的函数的顶层都有一个类似的catch块。如果线程上存在未捕获的异常,它将会终止该应用程序,主线程上的catch块将不会提供帮助。

+0

线程在顶层函数中有一个try/catch块。 – Andomar 2009-08-14 14:31:47

3

也许它是抛出你的异常的Logging.Log函数?

+0

日志功能很简单,并且有足够的磁盘空间可用。该程序在运行时保持单个StreamWriter处于打开状态,并通过锁定部分保护对它的访问。 – Andomar 2009-08-14 14:41:14

3

控制台程序在主函数退出时退出。由于DoWork只产生了一些线程,因此它将控制权立即返回到主体,并且由于Main没有其他任何事情可以退出并且程序结束。此时DoWork产生的线程也被杀死。

之前的工作意味着DoWork()中有某些东西等待那些现在立即返回(已损坏)的线程,或者该部分仍然有效,但过去需要很长时间返回的线程现在会中止并立即返回。

+0

DoWork()函数在所有工作完成之前不会返回,并且所有线程都已关闭。该计划多年来运行良好,处理了超过一百万个工作项目。 – Andomar 2009-08-14 14:30:00

+0

等待...我认为只有后台线程在产生它们的应用程序退出时才会被终止。 – Will 2009-08-14 14:32:40

+0

@Will:我认为这是Windows服务的行为。其他Windows应用程序像Joel所描述的那样描述 – Andomar 2009-08-14 14:42:41

2

过去,我设法让程序以与您类似的方式消失(没有异常痕迹,没有终止日志消息)。几乎所有的时间都与杀死堆栈有关(本网站的名称总是让我想起)。

您是否有可能突然尝试处理比平时更多的数据,或者使用重入例程,或者使用指针进行“智能”操作?

免责声明:我的经验是使用Win32 C++应用程序,而不是C#。

2

难道是内存泄漏?如果你的应用需要太多的内存,Windows将会杀死它。你可以检查你正在使用多少内存:如果它随着时间增长,你可能会有内存泄漏。

另一种可能性是某处你有代码调用Environment.Exit()。尝试通过您的代码进行全文搜索来仔细检查,您永远不知道!

+0

感谢您的提示。内存使用似乎不会增长,并且Exit()函数是我们检查的第一件事情之一:) – Andomar 2009-08-14 22:23:17

5

DoWork方法产生的线程之一可能抛出异常。在这种情况下,默认行为是进程终止。您可以通过使用AppDomain.UnhandledException事件覆盖默认行为来阻止发生这种情况。

2

小心,也有一些例外,即不能被捕获:OutOfMemoryException异常,StackOverflowException,因此你的程序将非常死,只是默默地。

+0

是的,但我希望这会触发DebugDiag并记录崩溃转储。 – Andomar 2009-08-14 22:14:00

+0

AFAIK'OutOfMemoryException'可以被捕获。 – CodesInChaos 2013-11-22 10:19:28