I dont know why but i can no longer interrupt my own thread.
thread = new Thread(new ParameterizedThreadStart(this.doWork));
thread.Start(param);
...
thread.Interrupt();
//in doWork()
try {
...
}
catch (System.Threading.ThreadInterruptedException)
{
//it never hits here. it use to
}
I search and i dont have any catch in my code and this is the only catch (System.Threading.ThreadInterruptedException). So what is going on? Using the debugger i can see my code run through the thread.Interrupt();. If i do thread.abort() i will catch a System.Threading.ThreadAbortException exception. Why is it catching that and not ThreadInterruptedException?
From BOL:
Interrupts a thread that is in the
WaitSleepJoin thread state.
If this thread is not currently
blocked in a wait, sleep, or join
state, it will be interrupted when it
next begins to block.
ThreadInterruptedException is thrown
in the interrupted thread, but not
until the thread blocks. If the thread
never blocks, the exception is never
thrown, and thus the thread might
complete without ever being
interrupted
BTW, you might be better off using the BackgroundWorker Class which supports cancelling.
From acidzombie24's comment to another answer:
So .abort is a better option? What i want to do is kill the thread but have it exist and call a few functions instead of outright death
Something like an event would be better.
Assuming you want to be able to signal each thread separately, before each worker thread is started create an AutoResetEvent and pass it to the thread.
When you want to interrupt the thread call Set on the event. In the worker thread check the state of the event regularly:
if (theEvent.WaitOne(TimeSpan.Zero)) {
// Handle the interruption.
}
(Regularly: needs to be defined by the requirements: overhead of checking vs. latency of interruption.)
To have a master interrupt, to signal all workers, use a ManualResetEvent which will stay signalled, and keep interrupting threads when they check, until explicitly Reset.
Related
I am reading multithreading in Albahari's c# in a nutshell. He says that if a thread (for example Main thread) creates and starts a worker thread , then an exception thrown by the worker thread cannot directly be caught and handled by the creating thread. Let me quote him verbatim:
"Any try / catch / finally blocks in effect when a thread is created are of no
relevance to the thread when it starts executing. Consider the following
program:
public static void Main()
{
try
{
Thread workerThread = new Thread (Go);
workerThread.Start();
}
catch (Exception ex)
{
// We'll never get here!
Console.WriteLine ("Exception!");
}
}
static void Go()
{
throw null; // Throws a NullReferenceException
}
Albahari goes on to say that:
"The try / catch statement in this example is ineffective, and the newly
created thread will be encumbered with an unhandled
NullReferenceException . This behavior makes sense when you consider
that each thread has an independent execution path."
So here is the crux of my question:
I don't get the relevance of "each thread has an independent execution path". I mean why should it matter if the execution paths are independent ? I mean when the workerThread throws an unhandled exception -- why can't the CLR just halt the Main thread and hand over the exception object to the catch block in the Main? What's stopping it ??
[NOTES:
The other related question How do I handle exceptions from worker threads and main thread in a single catch block? is NOT asking the same question --- and none of the elaborate answers express WHY can't the CLR marshal an unhandled exception from a worker thread to the Main thread
Similar question is asked about another language , C++, -- where the answers suggest that it has something to do with the two threads having different stacks and the logical impossibility of mixing the two while unwinding the stack during exception handling. I'm not sure whether those answers apply here to a managed execution environment , like that of c#.
]
The main thread might have already finished executing.
I know it is hard to understand at first, but the worker thread is not executed like a method call even if it looks like that. The thread is created inside that try-block, but the execution might happen much later or not at all. Source code in text form can not make this visible. There seems to be some kind of "spacial" proximity of the try-block and the thread, but the moment the thread is created, the spacial proximity is gone. The try block only handles any exceptions that happen while the thread is created, but the it is "detached" from it.
Analogy: The main thread is the manager (team lead) and the worker thread(s) are the workers (team members) reporting to that manager. The workers are working in their home office. In the morning the manager is sending them emails with tasks for the day ("execute method Go"). Since the manager can not see the workers doing their work, she can only notice any progress or lack of it, if the workers send progress reports from time to time. If workers fall off their chairs or down the stairs (exceptions), the manager would not know. The workers need to make sure to catch such exceptions and send an appropriate message to the manager to let her know. The manager is (in this case) not waiting around after sending the initial emails, but is doing other work in the meantime.
You are asking why the CLR can't halt the Main thread, and handle the exception of the child thread. Do you mean the main thread should always suspend execution automatically, immediately after launching a new Thread? This would be very unhelpful, since a program could then have at a maximum one and only one active thread. It would be the end of multithreading as we know it! So you probably mean that the CLR should offer a mechanism to do this suspension of execution on demand. Although such a mechanism is indeed not available, you can do something very close to it using tasks:
public static void Main()
{
try
{
Task workerTask = new Task(() =>
{
throw null;
}, TaskCreationOptions.LongRunning); // Use a dedicated thread
workerTask.Start();
workerTask.Wait();
}
catch (Exception ex)
{
Console.WriteLine("Exception!"); // It happens!
}
}
Let's say i have .NET Core 2.0/2.1 program.
There is a thread executing the following method. I want to stop it forcefully.
Important notes:
Cooperative multitasking (for example, with CancellationToken) is a good thing, but not the case
XY problem (https://en.wikipedia.org/wiki/XY_problem) does exist, but i just want to know if stopping this thread is actually possible
while (true)
{
var i = 0;
try
{
Console.WriteLine($"Still alive {i++}");
}
catch (Exception e)
{
Console.WriteLine($"Caught {e.GetType().Name}");
}
}
Tried several options:
Thread.Abort - throws PlatformNotSupportedException, not an option
Thread.Interrupt - only works for threads in WaitSleepJoin state, which is not the case
Calling native API methods such as TerminateThread from kernel32.dll on Windows. This approach has a lot of problems like non-released locks (https://msdn.microsoft.com/en-us/library/windows/desktop/ms686717(v=vs.85).aspx)
Concerns, from most important to least:
Releasing locks
Disposing objects in using directives
Actually collecting allocated objects
(as a corner case we can assume that out thread does not perform any heap allocations at all)
Use a ManualResetEventSlim. The instance will need to be available to both the thread you are trying to stop and the thread which will cause the stop.
In your while(true) loop, do something like this:
var shouldTerminate = mres.Wait(100);
if (shouldTerminate) { break; }
What this does is wait until the ManualResetEvent is put into a Set state, or 100ms, whichever comes first. The value returned indicates if the event is Set or Unset. You'll start off with the MRE in an Unset state, and when the control thread wishes to terminate the worker thread, it will call the Set method, and then it can Join the worker thread to wait for it to finish. This is important as in your loop you could perhaps be waiting on a network call to finish, and the worker won't actually terminate until you are back at the top of the loop again. If you need to, you could check the MRE with Wait at multiple points in the worker thread to prevent further expensive operations from continuing.
I have a thread that I am trying to discontinue. What I have done is the following.
randomImages = new Thread(new ThreadStart(this.chooseRandomImage));
randomImages.Start();
This is the method called by the thread
bool threadAlive = true;
public void chooseRandomImage()
{
while(threadAlive)
{
try
{
//do stuff
}
catch (Exception exe)
{
MessageBox.Show(exe.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
Now, upon clicking a stop thread button I simply set threadAlive to false.
Problem is the thread doesnt stop immediately, as if it has gathered a form of momentum.
How can a stop a thread instantly, and possibly restart it again?
private void butStopThread_Click(object sender, EventArgs e)
{
threadAlive = false;
if(threadAlive == false)
{
//do stuff
}
}
I am sorry, that IS the best way to do it. Using .NET 4.0 upward you should use tasks, not threads, and then there is this thing called CancellationToken that pretty much does the same as your variable.
Then, after cancelling, you wait until the processing is finishing. If that needs to happen fast, then - well - make the check for the cancellation more granular, i.e. check more often.
Aborting threads has possibly significant side effects as explained at http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation - this is why the method generally should not be used.
And no, stopped threads etc. can not be restarted magically - this you have to put into your logic (restart points, save points ,long running transaction in steps, remembering where it finished).
As a sidenote - if you insist on not using tasks and have access to the latest versin of .NET, Volatile is not needed if you use the Interlocked access class methods, which ago down to some assembler instructions that are thread safe per definition.
It is possible to terminate a thread from another thread with a call
to Abort, but this forcefully terminates the affected thread without
concern for whether it has completed its task and provides no
opportunity for the cleanup of resources. The technique shown in this
example is preferred.
You need to use Abort method BUT IS NOT RECOMMENDED
From the information provided by you, it seems the threadAlive variable is being accessed by both the worker thread and the UI thread. Try declaring threadAlive using volatile keyword which is ensure cross-thread access happens without synchronization issues.
volatile bool threadAlive;
To restart the thread, you first need to ensure that it performs all necessary cleanup. Use the Join method call on your thread object in the main/UI thread to make sure your thread terminates safely. To restart, simply invoke the Start method on the thread.
randomImages.Join();
We are using the TPL to queue long-running tasks into the threadpool.
Some of the tasks can block for some time, so we are using the following pattern to cancel them:
private void RunAction(Action action, CancellationTokenSourceWithException cts)
{
try
{
s_logger.Info("Starting action on thread ID: {0}", Utils.GetCurrentNativeThreadId());
Thread taskThread = Thread.CurrentThread;
cts.Token.Register(() => InterruptTask(taskThread));
s_logger.Info("Running next action");
action();
}
catch (Exception e)
{
cts.Cancel(e);
throw;
}
This way, calling cts.Cancel() will cause the task thread to be interrupted in case it is blocking.
This, however, has led to a problem: we don't know if the thread actually got the ThreadInterruptedException or not. It is possible that we call Thread.Interrupt() on it, but the thread will run to completion and the task will simply end. In that case, the threadpool thread will have a ticking bomb in the form of the ThreadInterruptedException, and whenver another task runs on this thread and attempts to block, it will get this exception.
A Thread.ResetInterrupted() method (similar to Thread.ResetAbort()) would be helpful here, but it does not seem to exist. We can use something like the following:
try
{
someEvent.Wait(10);
}
catch (ThreadInterruptedException) {}
To swallow the ThreadInterruptedException, but it looks ugly.
Can anyone suggest an alternative? Are we wrong to be calling Thread.Interrupt on threadpool threads? It seems like the easiest way to cancel tasks: cooperative cancellation using events etc. are much more cumbersome to use, and have to propagate into all classes that we use from the task.
You cannot do this because you don't know if/when the thread pool's threads will block when not running your own code!
Apart from the problems you mentioned, if a thread decides to block while not running your own code then the ThreadInterruptException will be unhandled and the app will immediately terminate. This is something you cannot work around with a try/block/catch guard because there is a race condition: the guard might have just completed when Thread.Interrupt is called, so if the runtime decides to have the thread block at that point you 'll get a crash.
So using Thread.Interrupt is not a viable option and you will definitely have to set up cooperative cancellation.
Apart from that, you should probably not be using the thread pool for these tasks in the first place (although there's not enough data to be . Quoting the docs (emphasis mine):
If you have short tasks that require background processing, the
managed thread pool is an easy way to take advantage of multiple
threads.
There are several scenarios in which it is appropriate to create and
manage your own threads instead of using thread pool threads:
...
You have tasks that cause the thread to block for long periods of time. The thread pool has a maximum number of threads, so a large
number of blocked thread pool threads might prevent tasks from
starting.
...
You might therefore want to consider using a thread pool of your own (there is an apparently very reputable implementation here).
Simple. You need to pass a CancellationToken to the action being called and act on it when cancellation is signalled. Messing with TPL threads with Interrupt is definitely the wrong action to take and will leave TPL in a "confused" state. Adopt the cancellation pattern all the way.
When a thread is canceled via Thread.Abort(), a ThreadAbortException is thrown inside the Thread on which Thread.Abort() was called on. This leads the thread to immediately stop its work and the exception bubbles up the call stack until it leaves the thread's main method. This causes the thread to be aborted.
What are the benefits of an ExceptionHandler for the ThreadAbortException in the threads main method where Thread.ResetAbort() is called, when the thread terminates itself anyway after the catch block due to stepping out its main method?
private void ThreadMainMethod( )
{
try
{
while(runningAllowed = true)
{
//Do some work here
}
}
catch ( ThreadAbortException )
{
Thread.ResetAbort( );
}
}
One scenario I can think of is that you want to take down the thread in a controlled manner. Let's say you have a worker thread that is polling some resource. If the application's main thread invokes Abort on the worker thread, a ThreadAbortException is thrown. You can then catch that exception in start method for the worker thread, call ResetAbort and then finish the method by releasing resource, closing open files/connections and so on:
public void ThreadStarter()
{
try
{
RunWorkerLoop();
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
}
// clean up and end gracefully
}
Probably the only reason you'd do that would be if you were in a great position to decide whether or not you should actually abort.
So perhaps the thread would catch it, check the status of something, and then go back about its work again. Though this does imply that you're basically using the '.abort()' to control the flow of this thread. And that's quite a bad idea. You should communicate with it in another way.
In general, I would think there are not many cases where this is a good idea, and it wouldn't be the advice for any particular pattern or implementation I can think of.
In you particular case it doesn't really make a difference, because the thread will be terminated once the method is done running.
However, in other case you may have a method that runs in an endless loop. In this case, you can shutdown the thread using the ThreadAbortException (I am not saying that you should, but you could). If the thread for some reason determines to continue despite the exception it needs to call ResetAbort to prevent the runtime to automatically rethrow the ThreadAbortException.
I found that calling ResetAbort() to be of great help in this elegant implementation of the WaitFor with time-out pattern .