Introduction
If you're using threads, a lot of situations may arise where it is useful to know from where the thread was started in order to determine the cause
of some issue (exception, inconsistency, <your type of problem here>). Instead of hard-coding this for every situation, a simple extension method
can suffice - extend at your leisure with exception handling, etc.
The Code
The code itself is short and sweet:
public static void Threaded(Action ac)
{
string callingstack = null;
if (GetCallingThreadStackTraces)
callingstack = (callingstack = Environment.StackTrace)
.Substring(callingstack.IndexOf("\r\n"));
new Thread(() => try { ac() } catch {
}).Start();
}
Using the Code
- Simply add the method in any class,
- Declare
GetCallingThreadStackTraces
as either a variable or a constant in scope, - And implement your error handling code in the
catch
statement to log to someplace you can access.
Notes and Comments
Notes on GetCallingThreadStackTraces
You'll probably want to disable stack traces in production code (if you're not releasing
with debug info).
You can also use it to only log the calling thread under certain circumstances (make it a parameter, base it on a parameter, etc.)
or to only run on certain machines where the problem is known to occur.
Regarding performance and task
If you're opening up a separate thread for some task that should be waited for / is resource intensive, the performance cost of the stack trace and wrapping code will be a non-factor.
This code is useful for .NET 3.5 and up (if you still develop for XP SP2 targets - an unfortunate reality for many). If you are using Task
rather than Thread
, you should be able to easily adapt the code for that eventuality.
Personal flavor
Use an extension method instead of manually creating threads everywhere. This behavior (and others) can then be implemented on-demand without rewriting any code.
Also, you can wire it up with some short-hand syntax and any additional code that you want for every thread (count the amount of threads created, add performance logging, etc).
Example, when wired up to the int
class as an extension method:
0.Threaded(() => );
This might not be in everyone's list of acceptable practices - but works rather well all-round. You can always extend
Thread
with a static method as well which might
be more universally acceptable.
C# 5.0
For C# 5.0+ users, you can add default parameters that log method names and code lines using compiler attributes - this can then provide a single-line stack track for production
code where stack traces are not available.
History
2012/11/23 - Posted.
Michiel du Toit is a software developer based in Bloemfontein, South Africa focusing on development using C# and SQL Server (both WinForms and ASP.NET).