How to check if Thread code runs in try-catch block - c#

I would like to validate our code and check if every Thread that we execute runs in try catch block.
A valid sample:
Thread loadDataThread = new Thread(new ThreadStart(LoadData));
public void LoadData()
{
try {/*do something*/}
catch(Exception ex) { /*Handle exception*/ }
}
Not valid sample:
Thread loadDataThread = new Thread(new ThreadStart(LoadData));
public void LoadData()
{
/* do something */
}
Is this something that could be verified with FxCop or some other tool. The similar rule could be applied for some other things eg. Timer Ticks etc...

See http://social.msdn.microsoft.com/Forums/en-US/vstscode/thread/a257a910-126e-4c8d-aab3-3199347346ec for an example of how to detect a wrapping try/catch block in an FxCop rule. What's actually quite a bit trickier to do is detect which methods are susceptible to being run from a background thread since they're not all spawned using obvious launchers like Thread.Start or ThreadPool.QueueUserWorkItem.
That said, you might want to reconsider switching your approach from adding wrapping try/catches to using custom thread launchers that add the try/catch for you. (You could then create an FxCop rule to verify that the custom launchers/helpers are being used instead of the base framework analogs.) This would have the advantage of allowing you to systematically apply other changes to all thread (e.g.: setting cultures, tracking launching stack trace for use in later exception logging, etc.) without needing to change all the methods run from spawned threads.

I do not know if you can add a custom rule for this in FXCop, but you could use Mono.Cecil to do this, but it is not that simple.

This is a very good resource for rolling your own FxCop rule. You may find many other by googling for the same.
I believe that you can start looking at callers for Thread constructor. Then in calling statement, you can get address of thread procedure by looking at the delegate parameter. Once method ref is obtained, you need inspect statements within method body for the structure you are hoping for.

this does not answer your question directly but is probably pertinent.
Are you interested in doing the above because you do not want your application to exit/crash when a thread throws an uncaught Exception? If yes, then you can add the following to your app.config file in the configuration section:
<runtime>
<legacyUnhandledExceptionPolicy enabled="1"/>
</runtime>
disclaimer Doing the above is not recommended but may be used in a situation of last resort.
Warning: If you decide to use the above your application will not report any errors and go on executing as best it can. As a result you should have a handler that will at least log any uncaught exceptions via
void AppStartup()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
//log error
}

Related

Any way to catch an exception occurring on a thread I don't own?

I'm using a crappy third party library because unfortunately I have no choice. This library creates a bunch of threads internally when I call it, and occasionally throws a NullReferenceException on one of these threads. Is there any way for me to catch these exceptions even though I don't own the thread that throws them? I have no way to change the third party code.
As a simple example to show the problem:
public static void main()
{
try
{
var crappyLib = new CrappyLibrary();
crappyLib.DoCrappyThings();
}
catch
{
Console.WriteLine("This never happens");
}
}
// I do not own the following code, I can't change it
public class CrappyLibrary
{
public void DoCrappyThings()
{
var t = new Thread(DoWork);
t.Start();
}
private void DoWork()
{
throw new ThisLibrarySucksException();
}
}
The thing worrying me most in the described case is abnormal thread termination inside that 3rd-party lib. Once a thread is throwing, you can't catch the exception via correct way because you're not the owner of that thread invocation (and it has no idea it should propagate the exception to you; unlike it happens in TPL, let say). So even if handling such exceptions via a global handler this could be incorrect way because the lib can appear in non-consistent state after any of such exceptions.
So the safe way here is to isolate the lib inside some scope and re-launch the scope after any exception. Let say, to load the lib into separate domain.
If your goal is to prevent early termination of your process because of these unhandled exceptions that are not under your control, then there exists the legacyUnhandledExceptionPolicy setting that you can add to your app.config that will prevent unhandled thread exceptions from terminating the whole process.
Obviously, the solution is not perfect, as unhandled exceptions can destabilize the state of the threads. But at least it's an option you can consider.
Please have a look at the documentation about this here to better understand the implications of turning on this setting.
Your app.config would have to look something like this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="1"/>
</runtime>
</configuration>
EDIT:
Just a thought, but perhaps the above setting, in combination with adding an event handler for AppDomain.UnhandledException can help you with your need.
Using AppDomain.UnhandledException, you can detect the failure, so that you know when you need to trigger a retry, or whatever else it is that you need to do in these cases.
And the legacyUnhandledExceptionPolicy setting would still be useful to prevent the process from shuting down, thus giving you the opportunity to perform the retry.
I hope this is helpful https://msdn.microsoft.com/en-GB/library/system.windows.forms.application.threadexception.aspx
You can try something like that (it's from the article)
Application.ThreadException += new ThreadExceptionEventHandler (ErrorHandlerForm.Form1_UIThreadException);
// Set the unhandled exception mode to force all Windows Forms errors to go through
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

handling errors through the async dll stack

I'm trying to handle errors that are passed through 2 dlls I've created. So Console.exe calls dll 1. dll 1 completes an async MQ message read and the handler calls dll 2. If dll 2 errors it passes the Exception (throw) without a problem. But the dll 1 (async) handler catch the throw from dll 2 and give me an unhandled by user message.. I have followed the msdn code to add in the IAsyncResult to keep the hander alive but the issue persists.
can anyone advise on how I should handle this stack and get the handler error returned to the console.exe program so I can present it to the user. Code below:-
Console.exe (snippet)
try
{
_msmq.MSMQ_GetMessage(_msgPath);
//set up the print of the number of queue messages
Console.WriteLine("Main thread: starting a timer");
Timer t = new Timer(ComputeBoundOp, _msgPath, 0, 2000);
Console.Write("Press any key to continue . . .");
Console.ReadKey(true);
t.Dispose(); // Cancel the timer now
}
catch (MessageQueueException _msgQex)
{
Console.WriteLine("An error occurred with the queue:- " + _msgQex);
}
catch (Exception _ex)
{
Console.WriteLine("An error occurred with the queue:- " + _ex);
}
dll 1
public void MSMQ_GetMessage(string _MQ_Path)
{
try
{
//set the correct message queue
MessageQueue _msgQ = new MessageQueue(_MQ_Path, QueueAccessMode.ReceiveAndAdmin);
//set the format of the message queue
_msgQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(_TwitterStreamFeed) });
_msgQ.ReceiveCompleted += new ReceiveCompletedEventHandler(_msgQ_RecieveCompleted);
IAsyncResult _result = _msgQ.BeginReceive();
_asyncList.Add(_result); // asyncList is a global variable of type System.Collections - > this allows the callback to remain open and therefore nit garbage collected while the async thread runs off on it's own
}
catch (Exception _ex)
{
throw new Exception("_msgQ_get Message threw the following error :- " + _ex);
}
}
//method to process message
public void _msgQ_RecieveCompleted(object sender, ReceiveCompletedEventArgs e)
{
try
{
//queue that have received a message
MessageQueue _mq = (MessageQueue)sender;
//get the messge off the queue
Message _mqmsg = _mq.EndReceive(e.AsyncResult);
//set the values back into a formatted struct
//now process your SQL....
Azure_SQL _azuresql = new Azure_SQL();
_azuresql.writeMessageToStorage((_TwitterStreamFeed)_mqmsg.Body);
//refresh queue just in case any changes occurred (optional)
_mq.Refresh();
//tell MessageQueue to receive next message when it arrives
_mq.BeginReceive();
}
catch (Exception _ex)
{
throw;
}
dll 2
public void writeMessageToStorage(_TwitterStreamFeed _msmq_message_as_TSF)
{
try
{
// now do something with the class - i..e write the values to the database
SqlConnection _azurecon = new SqlConnection(_AzuzeSQLConnection);
SqlCommand _sqlcmd = new SqlCommand();
//Setup the command string to call the stored procedure
//Add the parameter to the parameters collection of the command
blah blah blah......... Do SQL writing to Db
_azurecon.Open();
SqlDataReader _sqldr_tweet_place = _sqlcmd_place.ExecuteReader(CommandBehavior.CloseConnection);
}
//now close things off
_azurecon.Close();
}
catch (Exception _ex)
{
// Throw the error to preserve the original
throw;
}
The reason for this is that, internally, the MessageQueue class is explicitly swallowing the exception. Where the MessageQueue class raises the ReceiveCompleted event, it's inside of a try-catch statement - and the catch block is empty. Suffice it to say, if an exception occurs inside your ReceiveCompleted event handler, _msgQ_RecieveCompleted(), nothing's ever going to know it happened.
I see a couple of options, in order of preference.
Option 1 - Shift where the asynchronous call is made
Since this exception-swallowing behavior only occurs when using BeginReceive(), in MSMQ_GetMessage(), you can switch from using BeginReceive() to just Receive(). Then, make your call to MSMQ_GetMessage() asynchronous and any exception that gets thrown will be propagated as expected.
As a side note, a new(er) alternative for making asynchronous calls is available; the Task<> class. As opposed to the Thread class, Task<> has exception handling functionality built in. It does, however, require Framework 4 or higher. There is a good explanation of it's use described in the answer here.
Option 2 - Use a custom event
If refactoring the asynchronous call isn't an option, you can create a custom event in your class in 'dll 2' and subscribe to that event in 'Console.exe'. So when an exception occurs in _msgQ_RecieveCompleted(), you can raise the event and 'Console.exe' will be notified.
The MessageQueue.BeginReceive() method uses the standard .NET APM (Asynchronous Programming Model) pattern. It is very important to understand how it works to know how to properly deal with exceptions. Be sure to read the MSDN article, there are lots of other googable resources available.
In APM, the callback that tells you that a message was received in executed on a thread-pool thread. Which is a very efficient way to get code to run quickly. It is however also a very troublesome way when something goes wrong. The EndReceive() method call is likely to throw an exception, it does so to tell you that the receive operation could not be completed. A standard exception it will throw is ObjectDisposedException. Which will happen when the MessageQueue object gets disposed. In your case when your program terminates. You need to catch that exception and exit from your event handler, it is an expected exception and signals that nothing more useful is going to happen next since the queue was closed.
Then there's a raft of possible exceptions that can be raised by major mishaps in the message queue plumbing. Plus whatever you do with the message. Looks like you execute some Azure code, plenty of ways that can fall over. If you let such an exception escape from the callback method, like you do, then there's no catch clause anywhere in the call stack that is going to handle the exception. The standard way .NET deals with unhandled exceptions is to raise the AppDomain.UnhandledException event and terminate your program. If you didn't actually implement that event then there's nothing decent to look at to diagnose the reason your program ended, the Windows Error Reporting dialog has no good diagnostic.
Whether or not you should try to handle the exception and prevent the program from terminating is up to you. But it pretty strongly fits the "don't shoot the messenger" pattern, it is very unlikely your program can meaningfully continue to execute when such an exception is raised. It invariably takes a human to fix the problem, like restoring the network connection or fixing the message queue. If you do catch it then the odds that the same exception is raised over and over again is fairly likely. After all, there wasn't anything decent you could do in your code to repair the network.
So the best guidance here is to not try, just make sure that IT staff has a good diagnostic so they can repair the problem. Do implement the AppDomain.UnhandledException and display and log the e.UnhandledException.ToString() value. This will also let you learn the number of ways that your program can fail. There might be some conditions that are common enough to warrant catching, something like a temporary network outage. At that point you'll also know what to do about it, in other words what kind of code to write in the catch clause. There is no possible way you know what to write right now, you should therefore not try.
Last but not least, do note that you got yourself into this pickle because you used BeginReceive() unnecessarily. You've already got a perfectly good thread to do work on. But it doesn't do anything useful, it is stuck in the Console.ReadKey() method. Particularly in .NET 4.5 a very tricky method to call, it prevents other threads from writing anything to the console. So your error reporting won't work, it will deadlock when it tries to use Console.WriteLine() to write a diagnostic.
You might as well use MessageQueue.Read() instead. Now dealing with exceptions is a lot easier since they occur on the same thread. The MessageQueue.SynchronizingObject can also be helpful to get completion callbacks to occur on the main thread, but that only works in a GUI app, not in a console app.

Trace all handled exception

I am trying to understand why a deployed application is not working properly. I have pinned down the problem to a particular update routine. Sadly, the routine is embedded into a do nothing try-catch.
bool requireUpdate = false;
try
{
requireUpdate = !client.IsUpToDate();
}
catch{ }
I need a way to get the exception without having to recompile and do a deploy.
Is there is a way to modify the app.config file so it can trace all handled exceptions to a log file, regardless of how they have been handled?
Just because I discovered this today (and I really like resurrecting old questions with not-too-helpful answers!), since .NET4, there is a new event on AppDomain, which fires before any exception handling.
At some point in the setup code for your app (e.g. Program.Main, Application_OnStart, etc), you can add a handler:
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.FirstChanceException
+= FirstChanceException
// ...rest of your app startup
}
private static bool LogFirstChanceExceptions
{
get
{
return ConfigurationManager.AppSettings["logFirstChanceExceptions"]
.Equals(bool.TrueString)
}
}
private static void FirstChanceException(object sender,
FirstChanceExceptionEventArgs e)
{
if (e != null &&
e.Exception != null &&
LogFirstChanceExceptions)
{
Console.Error.WriteLine("First-chance {0}: {1}",
e.Exception.GetType(),
e.Exception.Message);
}
}
}
(Untested, no warranty, etc. Not pictured: any re-entrancy handling, in case the FirstChanceException handler itself throws an exception)
Doesn't help the OP, but it might help people who can recompile, to include something that allows them to toggle this kind of tracing in the future.
Unfortunately there is nothing that can be done about handled exceptions, as they are handled (even if very badly, as in your case).
The best way to get them will be to rewrite/recompile/deploy.
UPDATED
CLR profiling can help ya!
Have a look at this link:
http://msdn.microsoft.com/en-us/magazine/cc301839.aspx
You can basically track your exceptions:
"he profiling API offers an extensive set of callbacks that depict in detail the search, unwind, and finally phases of the exception handling cycle. An interesting profiling scenario would monitor managed exceptions and provide additional information such as the Win32 thread that threw the exception, the function that was on the top of the stack, the arguments of that function, and the locals that were in scope at the point where the exception occurred."
Use low level debuggers, such as WinDbg you will be able to know first chance exceptions.
Tricks I've used for this in Java:
Go through all of the catch blocks in the application, looking for empty ones. Add a debug or trace message to the block saying something like, "Catching expected exception", and the exception. You should have this anyway, and set a policy that silently swallowing exceptions is absolutely not acceptable.
If that fails to flush out the exception, recompile the base Exception, add a block to the no-arg constructor to log a stack trace if the application is in debug (or trace) mode. Obviously this is easier to do if your application/library has its own Exception heirarchy, but there are ways to inject this behavior (here the way to do this in C# would be distinct from how I'd accomplish this)
There's another option, but it may or may not be pretty: Moles.
Technically used for unit testing, Moles allows you to replace any .NET method with a delegate. You might be able to use it to replace that method with your delegate that does what you want instead.
You might be able to replace the original method with a delegate that calls client.IsUpToDate() so you can snag the exception instead?
Moles is part of Pex:
http://research.microsoft.com/en-us/projects/pex/default.aspx
This solution may be what you are looking for.
Basically the instruction is to use this block of code:
System.Diagnostics.EventLog.WriteEntry("MyEventSource", exception.StackTrace,
System.Diagnostics.EventLogEntryType.Warning);
Additionally the app.config from that same link seems to be like so:
<system.diagnostics>
<switches>
<add name="MySwitch" value="Verbose" />
</switches>
<trace autoflush="true">
<listeners>
<add name="EventLogger"
type="System.Diagnostics.EventLogTraceListener"
initializeData="NameOfYourApplication" />
</listeners>
</trace>

InvokeRequired Exception Handling

I noticed a few strange behaviors in a Windows Forms scenario which involves threads and UI, so, naturally, this means making use of the InvokeRequired property. The situation: my application makes use of a thread to do some work and the thread sends an event into the UI. The UI displays a message based on an Internationalization system which consists of a dictionary with keys. The I18N system cannot find a key in the dictionary and crashes.
Notes: application is in Debug Mode and I have a try-catch over the entire "Application.Run();" back in Program.cs. However, that try-catch is not reached, as what I will discuss here is based on inner Exception handling, but I mentioned it just in case.
So now here comes the fun parts:
Why, for the life of me, does Visual Studio "censor" exception information from me? In the code below, you will see on the if (InvokeRequired) branch, a try-catch. I log the exception. ex.InnerException is NULL and the provided ex.StackTrace is anemic (only 1 step in it). Now if I comment the try-catch and simply let it crash via the Debugger, I get a much ampler stack trace. Why is that?
To make things worse, neither of the two stack traces versions contain any information about the i18N crash. They just say "The given key was not present in the dictionary." and give me a stack trace up to the Invoke declaration.
On the else branch (that is, InvokeRequired == false), if I put a try-catch, I can successfully catch my Exception back to the i18n system. As you can see, I tried to send my exception with InnerException back to the InvokeRequired == true branch. However, even so, InnerException stays NULL there and I cannot access my i18N error.
I am puzzled by all these things and maybe somebody can help shed some light over here. If you got really strong lanterns that is.
Here is the function's code.
private delegate void AddMessageToConsole_DELEGATE (frmMainPresenter.PresenterMessages message);
private void AddMessageToConsole (frmMainPresenter.PresenterMessages message)
{
if (InvokeRequired)
{ //Catching any errors that occur inside the invoked function.
try { Invoke(new AddMessageToConsole_DELEGATE(AddMessageToConsole), message); }
catch (Exception ex) { MSASession.ErrorLogger.Log(ex); }
//Invoke(new AddMessageToConsole_DELEGATE(AddMessageToConsole), message);
}
else
{
string message_text = ""; //Message that will be displayed in the Console / written in the Log.
try
{
message_text = I18N.GetTranslatedText(message)
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
txtConsole.AppendText(message_text);
}
}
Yes, this is built-in behavior for Control.Invoke(). It only marshals the deepest nested InnerException back to the caller. Not so sure why they did this, beyond avoiding reporting exceptions that were raised by the marshaling code and would confuzzle the reader. It was done explicitly, you cannot change the way it works.
But keep your eyes on the ball, the real problem is that the string indeed cannot be found in the dictionary. The reason for that is that your background thread runs with a different culture from your UI thread. Different cultures have different string comparison rules. You either need to give your dictionary a different comparator (StringComparer.InvariantCulture) or you should switch your background thread to the same culture as your UI thread.
Dealing with a non-system default culture in your UI thread can be difficult, all other threads will be started with the system default. Especially threadpool threads are troublesome, you don't always control how they get started. And culture is not part of the Thread.ExecutionContext so doesn't get forwarded. This can cause subtle bugs, like the one you ran into. Other nastiness is, say, SortedList which suddenly becomes unsorted when read by a thread that uses a different culture. Using the system default culture is strongly recommended. Its what your user is likely to use anyway.
The call stack problem is a known issue with Control.Invoke. You lose the call stack. Sorry. This is because it is rethrown on the UI thread using throw ex;.
The best solution would be to replace the background thread with a background Task. Note: this solution is only available for .NET 4.0. The Task class properly marshals exceptions. I wrote a blog entry about reporting progress from tasks, and the code in that blog entry will allow you to catch any UI update errors in the background thread, preserving the original exception and its call stack.
If you can't upgrade to .NET 4.0 yet, there is a workaround. Microsoft's Rx library includes a CoreEx.dll which has an extension method for Exception called PrepareForRethrow. This is supported in .NET 3.5 SP1 and .NET 4.0 (and SL 3 and SL 4). You'll need to wrap your UI updater method with something a little uglier:
private delegate void AddMessageToConsole_DELEGATE (frmMainPresenter.PresenterMessages message);
private void AddMessageToConsole (frmMainPresenter.PresenterMessages message)
{
if (InvokeRequired)
{
// Invoke the target method, capturing the exception.
Exception ex = null;
Invoke((MethodInvoker)() =>
{
try
{
AddMessageToConsole(message);
}
catch (Exception error)
{
ex = error;
}
});
// Handle error if it was thrown
if (ex != null)
{
MSASession.ErrorLogger.Log(ex);
// Rethrow, preserving exception stack
throw ex.PrepareForRethrow();
}
}
else
{
string message_text = ""; //Message that will be displayed in the Console / written in the Log.
try
{
message_text = I18N.GetTranslatedText(message)
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
txtConsole.AppendText(message_text);
}
}
Note: I recommend you start a migration away from ISynchronizeInvoke. It is an outdated interface that is not carried forward into newer UI frameworks (e.g., WPF, Silverlight). The replacement is SynchronizationContext, which supports WinForms, WPF, Silverlight, ASP.NET, etc. SynchronizationContext is much more suitable as an abstract "thread context" for a business layer.
Invoke on a Windows.Forms object causes the function to be invoked on a separate thread. If an Exception is thrown in your invoked function, the Exception is caught and a new TargetInvocationException is thrown.
This TargetInvocationException contains the initial Excpetion in it's InnerException property.
So, try to do it this way:
catch (TargetInvocationException ex) { MSASession.ErrorLogger.Log(ex.InnerException); }
Edit: Also, if you expand the InnerException property in the debugger, you will be able to access it's stacktrace, even if only as plain text.

Is there a good method in C# for throwing an exception on a given thread

The code that I want to write is like this:
void MethodOnThreadA()
{
for (;;)
{
// Do stuff
if (ErrorConditionMet)
ThrowOnThread(threadB, new MyException(...));
}
}
void MethodOnThreadB()
{
try
{
for (;;)
{
// Do stuff
}
}
catch (MyException ex)
{
// Do the right thing for this exception.
}
}
I know I can have thread B periodically check, in thread safe way, to see if a flag has been set by thread A, but that makes the code more complicated. Is there a better mechanism that I can use?
Here is a more fleshed out example of periodically checking:
Dictionary<Thread, Exception> exceptionDictionary = new Dictionary<Thread, Exception>();
void ThrowOnThread(Thread thread, Exception ex)
{
// the exception passed in is going to be handed off to another thread,
// so it needs to be thread safe.
lock (exceptionDictionary)
{
exceptionDictionary[thread] = ex;
}
}
void ExceptionCheck()
{
lock (exceptionDictionary)
{
Exception ex;
if (exceptionDictionary.TryGetValue(Thread.CurrentThread, out ex))
throw ex;
}
}
void MethodOnThreadA()
{
for (;;)
{
// Do stuff
if (ErrorConditionMet)
ThrowOnThread(threadB, new MyException(...));
}
}
void MethodOnThreadB()
{
try
{
for (;;)
{
// Do stuff
ExceptionCheck();
}
}
catch (MyException ex)
{
// Do the right thing for this exception.
}
}
This is NOT a good idea
This article talks about ruby's timeout library. which throws exceptions across threads.
It explains how doing such a thing is fundamentally broken. It's not just broken in ruby, it's broken anywhere that throws exceptions across threads.
In a nutshell, what can (and does) happen is this:
ThreadA:
At some random time, throw an exception on thread B:
ThreadB:
try {
//do stuff
} finally {
CloseResourceOne();
// ThreadA's exception gets thrown NOW, in the middle
// of our finally block and resource two NEVER gets closed.
// Obviously this is BAD, and the only way to stop is to NOT throw
// exceptions across threads
CloseResourceTwo();
}
Your 'periodic checking' example is fine, as you're not actually throwing exceptions across threads.
You're just setting a flag which says "throw an exception the next time you look at this flag", which is fine as it doesn't suffer from the "can be thrown in the middle of your catch or finally block" problem.
However, if you're going to do that, you may as well just be setting an "exitnow" flag, and using that and save yourself the hassle of creating the exception object. A volatile bool will work just fine for that.
There are enough problems with exceptions that can be thrown on threads by other mechanisms, like aborting threads and the likes, that you should find another way of doing it.
An exception is a mechanism used to signal that a process has experienced something exceptional that it cannot deal with. You should try to avoid writing the code so that an exception is used to signal that something else has experienced something exceptional.
That other thread will most likely not know how to handle the exception in all cases where it could be thrown by your code.
In short, you should find some other mechanism for aborting your threads than using exceptions.
Use event objects or similar to tell a thread to abort its processing, that's the best way.
What Orion Edwards is saying is not entirely true: is not the "only" way.
// Obviously this is BAD, and the only way to stop is to NOT throw
// exceptions across threads
Using CER (Constrained Execution Regions) in C# allows you to release your resources as an atomic operation, protecting your code from inter-thread exceptions. This technique is used by several classes of the .NET Framework which work with Windows' native API, where an unreleased handle may cause a memory leak.
See http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions.aspx
The following example shows how to reliably set handles by using the PrepareConstrainedRegions method. To reliably set a handle to a specified pre-existing handle, you must ensure that the allocation of the native handle and the subsequent recording of that handle within a SafeHandle object is atomic. Any failure between these operations (such as a thread abort or out-of-memory exception) will result in the native handle being leaked. You can use the PrepareConstrainedRegions method to make sure that the handle is not leaked.
As simple as:
public MySafeHandle AllocateHandle()
{
// Allocate SafeHandle first to avoid failure later.
MySafeHandle sh = new MySafeHandle();
RuntimeHelpers.PrepareConstrainedRegions();
try { }
finally // this finally block is atomic an uninterruptible by inter-thread exceptions
{
MyStruct myStruct = new MyStruct();
NativeAllocateHandle(ref myStruct);
sh.SetHandle(myStruct.m_outputHandle);
}
return sh;
}
While researching another issue, I came across this article which reminded me of your question:
Plumbing the Depths of the ThreadAbortException using Rotor
It shows the gyrations that .NET goes through to implement Thread.Abort() -- presumably any other cross-thread exception would have to be similar. (Yeech!)
I'm interested to know why you would want to do this. There's not an easy way to do it, because it's not a good practice. You should probably go back to your design and figure out a cleaner way to accomplish the end goal.
I don't think that's a good idea..
Take another crack at this problem - Try using some other mechanism like shared data to signal between threads.
Like the others, I'm not sure that's such a good idea, but if you really want to do it, then you can create a subclass of SynchronizationContext that allows posting and sending delegates to the target thread (if it's a WinForms thread the work is done for you as such a subclass already exists). The target thread will have to implement some sort of a message pump equivalent though, to receive the delegates.
#Orion Edwards
I take your point about an exception being thrown in the finally block.
However, I think there is a way - using yet another thread - of using this exception-as-interrupt idea.
Thread A:
At some random time, throw an exception on thread C:
Thread B:
try {
Signal thread C that exceptions may be thrown
//do stuff, without needing to check exit conditions
Signal thread C that exceptions may no longer be thrown
}
catch {
// exception/interrupt occurred handle...
}
finally {
// ...and clean up
CloseResourceOne();
CloseResourceTwo();
}
Thread C:
while(thread-B-wants-exceptions) {
try {
Thread.Sleep(1)
}
catch {
// exception was thrown...
if Thread B still wants to handle exceptions
throw-in-B
}
}
Or is that just silly?

Categories