I’m trying to code a bulletproof timeout function in my app that fires no matter what my main thread is doing. ExceptionConstraints work perfectly for this and I use them as part of my state machine architecture. Unfortunately, .Net Micro only allows one ExceptionConstraint (see https://www.ghielectronics.com/community/forum/topic?id=23020 if you’re interested ) so I can’t use a second one for my mission timeout. However, I can accomplish the same thing if I could figure out how to throw an exception in the calling thread from either 1) a timer callback or 2) another thread that does nothing but look for the timeout expiring. Unfortunately I haven’t been able to throw an exception that gets caught in the calling thread from either a timer callback or a separate thread.
@ Mike - Thanks for the quick response. I’ve been poking around the web and I can’t figure out what you mean by trying the interrupt method on a thread object. Can you be a little more specific?
@ Gene - when you create a thread you get a Thread object.
in your thread method you enclose your code in a try/catch.
```cs
void runMethod()
{
try
{
.... processing
}
catch (InterruptException)
{
... cleanup
}
}
I might have the specific interrupt exception wrong.
@ Mike - Are you sure .NETMF has the Interrupt method on the Thread class? You might be thinking of Thread.Abort which will throw a ThreadAbortException on the target thread.
I can’t find a Thread.Interrupt method but as Taylorza mentioned I have tried Thread.Abort() in my missionTimeoutThread. It throws an exception all right but only for itself, the main thread that calls missionTimeoutThread doesn’t catch it. There’s an example below and here is what shows up in the debug output window. A breakpoint in the main thread catch block never fires so I’m pretty sure my main thread doesn’t know the missionTimerThread aborted.
Still looking for ideas of a definitive “can’t be done, what the heck are you thinking?” statement.
Program Started
I = 0 missionTimedOut = False
I = 1 missionTimedOut = False
I = 2 missionTimedOut = False
I = 3 missionTimedOut = False
I = 4 missionTimedOut = False
I = 5 missionTimedOut = False
I = 6 missionTimedOut = False
I = 7 missionTimedOut = False
I = 8 missionTimedOut = False
I = 9 missionTimedOut = False
Exceeded mission timeout, trying to throw exception that will get caught in main
#### Exception System.ArgumentException - 0xfd000000 (3) ####
#### Message:
#### System.Threading.Thread::Abort [IP: 0000] ####
#### ThreadingTest.Program::checkMissionTimeout [IP: 002c] ####
A first chance exception of type ‘System.ArgumentException’ occurred in mscorlib.dll
An unhandled exception of type ‘System.ArgumentException’ occurred in mscorlib.dll
Uncaught exception
The thread ‘’ (0x3) has exited with code 0 (0x0).
I = 10 missionTimedOut = True
I = 11 missionTimedOut = True
I = 12 missionTimedOut = True
I = 13 missionTimedOut = True
using System;
using Microsoft.SPOT;
using System.Threading;
namespace ThreadingTest
{
public class Program
{
public static Thread missionTimeoutThread = new Thread(checkMissionTimeout);
public static DateTime missionStartTime = new DateTime();
public static void Main()
{
Debug.Print("Program Started");
missionStartTime = DateTime.Now;
missionTimeoutThread.Start();
while (true)
{
try
{
for (int i = 0; i < 1000000; i++)
{
Debug.Print("I = " + i.ToString() + " missionTimedOut = " + missionTimedOut.ToString());
Thread.Sleep(1000);
}
}
catch (Exception currentException)
{
Debug.Print(currentException.Message);
}
}
}
private static TimeSpan missionTimeout = new TimeSpan(0, 0, 0, 10);
private static bool missionTimedOut = false;
private static void checkMissionTimeout()
{
while(!missionTimedOut)
{
if (DateTime.Now - missionStartTime > missionTimeout)
{
Debug.Print("Exceeded mission timeout, trying to throw exception that will get caught in main");
missionTimedOut = true;
missionTimeoutThread.Abort();
}
else
Thread.Sleep(2000);
}
}
}
}
If I understand those correctly, my main thread sits and waits at the resetEvent call until the calling thread sets the event. I need my main thread to keep running and regardless of what it’s doing, respond to the timeoutThread. The only way I know how to do that is by throwing an exception in the main thread but if it can be done with resetEvent, I’d be happy to hear how.
I understand. Indeed ResetEvent would not work the way you want, here.
Then you could re-throw the exception you have caught in the catch() clause. This will throw the exception to the parent caller, that would of course use a try/catch block to handle it, like in the called thread.
I’ve tried something like that without success. If the exception, or timer callback or whatever thing I’m using to detect a timeout happens in the timeoutThread, I haven’t figured out how to throw or re-throw an exception that gets caught in the main thread catch block.
In your thread, the one that will catch the AbortException, you should add a “throw” statement in your catch clause.
Pseudo code would then give something like this :
//Main
try
{
// Whatever
}
catch (ThreadAbortException exAbort)
{
// Deal with your thread abort here
}
catch (Exception ex)
{
// Handle other exceptions here
}
// The thread
try
{
// your code
}
catch (ThreadAbortException exAbort)
{
// Do some cleanup if needed
throw;
}
catch (Exception ex)
{
// Handle other exceptions here
}
You could even re-throw another kind of exception (“throw new OutOfMemoryException;”, for example), although I wonder if it would be really useful.
I might not get exactly what you are saying but I tried this and it never gets to the catch block in the timeoutThread, it just throws an expetion at missionTimeoutThread.Abort.
I know I can make this work buy setting a public variable that the main thread can see when the timeoutThread determines the mission has timed out. It isn’t as bulletproof as an exception because my main thread has to get to the code that checks the public variable.
@ Jay Jay - that is an interesting piece of code but I’m still not sure a thread in a separate domain can throw an exception that the original main thread will see.