I have a Timer which has to cancel a Thread if it needs too much time.
System.Timers.Timer timer_timers = new System.Timers.Timer();
Thread thread = new Thread(startJob);
thread.Name = "VICTIM_THREAD";
when starting the Thread method I start the Timer and pass the current Thread to the event as parameter.
public void startJob()
{
Debug.WriteLine("Name: " + Thread.CurrentThread.Name);
timer_timers.Elapsed += (sender, e) => T_Elapsed(sender, e, Thread.CurrentThread);
timer_timers.Interval = 5000;
// Start simulation process
while (true)
{
Thread.Sleep(700);
Debug.WriteLine("Thread: " + Thread.CurrentThread.Name + " ALIVE: " + thread.IsAlive);
}
}
Timer event:
private void T_Elapsed(object sender, ElapsedEventArgs e, Thread currentThread)
{
// EDIT: show the correct NAME! of the thread
Debug.WriteLine("Name: " + currentThread.Name);
System.Timers.Timer tim = sender as System.Timers.Timer;
currentThread.Abort(); // <-- this line throws exception
if (tim != null)
{
tim.Stop();
}
}
But the Abort call throws me an Exception:
'Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack'
and the thread remains alive.
If I start the timer before the startJob() and pass the thread directly it works fine.
public void startThread()
{
timer_timers.Elapsed += (sender, e) => T_Elapsed(sender, e, thread);
timer_timers.Interval = 5000;
timer_timers.Start();
thread.Start();
}
public void startJob()
{
// Start simulation process
while (true)
{
Thread.Sleep(700);
Debug.WriteLine("Thread: " + Thread.CurrentThread.Name + " ALIVE: " + thread.IsAlive);
}
}
Question: Why does the Thread.CurrentThread version not work? is it because I would also have to abort the timer thread? What am I missing here?
Answers I found to this exception like this and this are from different context and don't really help me to understand exactly why.
EDIT: I know that this is the wrong way to abort or cancel a thread. The job it is supposed to do is to open a SerialPort. But once every ~200-th time the thread will just never return and I need to kill it nevermind the consequences. the simulation while loop is may be a bad example.
As noted in the comments, you should not be using
Abort. Even if you do, here is the issue with the way you're using it:Timers don't run on your thread. They run on the thread pool thread. Hence
Thread.CurrentThreadused in your lambda is going to be that thread pool thread.Here is what you should be doing if you want to abort the thread which is creating the timer: Capture the thread in a variable outside the lambda.
But you should be finding another way to terminate your thread more gracefully, or to rework your code to not need explicit threading.