如何确定导致.NET线程停止的原因?

时间:2011-01-31 21:28:37

标签: .net multithreading logging

我有一个用C#编写的Windows服务,它产生了几个工作线程。这些线程应该每隔X分钟循环一次,直到服务停止,这在大多数情况下都能正常工作。但是,有一个线程似乎无缘无故停止。我们已经有了一个try / catch块,其中包含了线程整个函数的日志代码,但它从不记录任何异常。

在.NET中,有没有办法监视来自另一个进程的线程并记录何时/为何/如何停止?

更多详情

产生线程的代码如下所示:

try
{
    // Create a new thread for processing Incoming Emails
    IncomingEmailThread = new Thread(new ThreadStart(ProcessIncomingEmails));
    IncomingEmailThread.Start();

    LogEvent("Service Started", EventLogEntryType.Information);
}
catch (Exception e)
{
    LogEvent(e.Message, EventLogEntryType.Error);
}

线程内的代码如下所示:

while (!Closing)
{
    try
    {
        // Wait for 5 minutes before running.
        InterruptableSleep.WaitOne(300000, false);

        // Process the incoming email for all instances
        string[] Instances = Settings.GetAllInstances();
        foreach (string Instance in Instances)
        {
            Logic.IncomingEmail IncomingEmailInstance = new Logic.IncomingEmail(Instance);
            IncomingEmailInstance.CreateRecordsFromIncomingEmail();
        }
    }
    catch (Exception ex)
    {
        // Log the exception and then eat it so it doesn't stop the thread
        LogEvent(ex.Message + "\r\n" + ex.StackTrace, EventLogEntryType.Error);
    }
}

问题不是由Closing标志引起的,因为此循环通常会在停止工作之前运行几天。问题不是CreateRecordsFromIncomingEmail()内部的异常,因为catch块没有记录任何异常。我们的日志代码直接写入Windows事件日志,我们在整个产品中使用它,它非常可靠。

不幸的是,我们无法使用调试器,因为我们只在一台生产服务器上看到了这个问题。我们无法在开发人员或任何其他服务器上重现它。

7 个答案:

答案 0 :(得分:3)

如果你发布了一些代码,包括产生线程的函数,那会有所帮助。 怀疑导致多种可能的解释

死锁

你的线程不再存在,因为它卡在一些锁中。仔细检查(如果有的话)所有锁定指令并注意数据库事务

运行标志设置太晚

我遇到类似的问题,一个线程从未在Mono中开始,在类似于你的场景中。

但是,如果你有这样的代码:

{
    Thread t = new Thread(Method);
    t.Start();
    Run = true;
}

void Method()
{
    while(Run)
    { ... }
}

那么你可能会遇到问题,具体取决于你设置Run = true的位置。在这种情况下,在Start()之后,您可能会认为花费一些时间让线程到达其控制点,但实际上并非如此。

如果没有关于代码的进一步信息,我可能会从你的描述中想象你有这样的问题(可以处理ThreadAbortException或ThreadInterruptException来记录但最终会传播,所以情况并非如此)

反正

您询问了如何调试:使用Visual Studio,您可以“连接到进程”并附加到正在运行的进程,获取线程列表等等。

答案 1 :(得分:0)

你确定它是你的一个工作线程正在停止吗? (与计时器线程或其他东西相反)

答案 2 :(得分:0)

附上调试器并查看。

答案 3 :(得分:0)

在Visual Studio 2008中,如果在调试时暂停应用程序,则可以选择Debug - > Windows - >线程(或点击 Ctrl + Alt + H )查看当前正在执行的线程。

从那里你可以双击一个线程,看看它目前在哪里。这可能表明,例如,您的帖子在调用Monitor.EnterWaitHandle.WaitOne或类似内容时是否已陷入僵局。

此外,如果你的帖子已经真的退出了,至少你可以通过看到它在列表中不存在来确认。

答案 4 :(得分:0)

也许您的日志记录有异常,您无法记录它们。添加另一种日志机制。临时邮件每个例外你自己。

如果您登录到文件系统,请检查您的服务用户对文件系统的写入权限。

答案 5 :(得分:0)

您是否考虑过使用AppDomain.UnhandledException事件注册处理程序?

答案 6 :(得分:0)

我们从来没有找到解决方案,但问题停止了。我们决定只添加一些日志代码,以防它再次发生。