How can I determine what caused a .NET thread to stop?
I have a Windows service written in C# that spawns several worker threads. Those threads are supposed to loop every X minutes until the service is stopped, which works very well in most cases. But, there is one thread that appears to be stopping for no reason. We already have a try/catch block with logging code around the thread's entire function, but it never logs any exceptions.
In .NET, is there any way to monitor a thread from another process and record when/why/how it stopped?
More details
The code that spawns the thread looks like this:
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);
}
And the code inside the thread looks like this:
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);
}
}
The problem is开发者_Go百科 not caused by the Closing flag, because this loop usually runs for several days before it stops working. The problem is not an exception inside CreateRecordsFromIncomingEmail(), because the catch block has not logged any exceptions. Our logging code writes directly to the Windows event log, we use it throughout the product, and it is very reliable.
Unfortunately, we can't use a debugger, because we've only seen the problem on one production server. We haven't been able to reproduce it in dev, or on any other servers.
if you posted some code, including the function that spawns the thread, it would help. Doubt leads to multiple possible explanations
Deadlock
Your thread is not alive anymore because it's stuck in some locks. Double check (if any) all the lock instructions and also pay attention to DB transactions
Running flag set too late
I had a similar problem with a thread never starting at all in Mono, in a scenario similar to yours.
But, if you have code such as this:
{
Thread t = new Thread(Method);
t.Start();
Run = true;
}
void Method()
{
while(Run)
{ ... }
}
then you may get problems depending in what position you set Run=true. In this case, after Start()
, you might think that it will take some time for the thread to reach its control point, but it's actually not true.
Without further information about your code, I might imagine, from your description, that you have a problem like this (ThreadAbortException or ThreadInterruptException can be handled to log but will ultimately propagate, so that's not the case)
Anyway,
You asked how to debug: with Visual Studio you can "connect to process" and attach to your running process, getting the thread list and so on.
Are you sure it is one of your worker threads that is stopping? (As opposed to a timer thread or something)
Attach a debugger and have a look.
In Visual Studio 2008 if you pause an app while debugging, then you can select Debug -> Windows -> Threads (or hit Ctrl + Alt + H) to see the threads that are currently executing.
From there you can double-click on a thread to see where it is at the moment. This can possibly indicate if, e.g., your thread is deadlocked on a call to Monitor.Enter
or WaitHandle.WaitOne
or something like that.
Also, if your thread has really exited, at least you can confirm this by seeing that it is not present in the list.
Maybe your logging have exception and you cant log them. Add another logging mechanism. Temporary mail every exception yourself.
If you logging to file system, check your service user's write access to file system.
Have you considered registering a handler with the AppDomain.UnhandledException event?
We never did find a solution, but the problem stopped happening. We decided to just add some logging code in case it ever happens again.
精彩评论