How to Kill a C# Thread? - c#

I've got a thread that goes out and looks up data on our (old) SQL server.
As data comes in, I post information to a modal dialog box - the user can't & shouldn't do anything else while all this processing is going on. The modal dialog box is just to let them see that I'm doing something and to prevent them from running another query at the same time.
Sometimes (rarely) when the code makes a call to the SQL server, the server does not respond (IT has it down for maintenance, the LAN line got cut, or the PC isn't on the network) or the person doing the query runs out of time. So, the modal dialog box does have a cancel button.
The Thread object (System.Threading.Thread) has IsBackground=true.
When someone clicks Cancel, I call my KillThread method.
Note: I can NOT use the BackgroundWorker component in this class because it is shared with some Windows Mobile 5 code & WM5 does not have the BackgroundWorker.
void KillThread(Thread th) {
if (th != null) {
ManualResetEvent mre = new ManualResetEvent(false);
Thread thread1 = new Thread(
() =>
{
try {
if (th.IsAlive) {
//th.Stop();
// 'System.Threading.Thread' does not contain a definition for 'Stop'
// and no extension method 'Stop' accepting a first argument of type
// 'System.Threading.Thread' could be found (are you missing a using
// directive or an assembly reference?)
th.Abort();
}
} catch (Exception err) {
Console.WriteLine(err);
} finally {
mre.Set();
}
}
);
string text = "Thread Killer";
thread1.IsBackground = true;
thread1.Name = text;
thread1.Start();
bool worked = mre.WaitOne(1000);
if (!worked) {
Console.WriteLine(text + " Failed");
}
th = null;
}
}
In my Output Window, I always see "Thread Killer Failed" but no exception is ever thrown.
How should I stop a thread?
The best related posts I found where the two below:
How to Kill Thread in C#?
How to kill a thread instantly in C#?
EDIT:
There seems to be some confusion with the method I listed above.
First, when someone clicks the cancel button, this routine is called:
void Cancel_Click(object sender, EventArgs e) {
KillThread(myThread);
}
Next, when I go in to kill a thread, I'd rather not have to wait forever for the thread to stop. At the same time, I don't want to let my code proceed if the thread is still active. So, I use a ManualResetEvent object. It should not take a full second (1000ms) just to stop a thread, but every time the WaitOne method times out.
Still listening for ideas.

Short Answer: You don't. Normally you do it by signaling you want to quit.
If you're firing an SQL query, do it asynchronously (pardon my spelling), and cancel it if necessary. That really goes for any lengthy task in a separate thread.
For further reading see Eric Lippert's articles:
Careful with that axe, part one: Should I specify a timeout? and Careful with that axe, part two: What about exceptions?
Edit:
How do you call SQL Server? ADO, TDS, Standard/Custom Library, etc... ?
THAT call should be made asynchrone.
Thus: StartOpeningConnection, WaitFor OpeningComplete, StartQuery, WaitFor QueryComplete, Start CloseConnection, WaitFor CloseConnectionComplete etc. During any of the waits your thread should sleep. After waking up, Check if your parent thread (the UI thread) has cancelled, or a timeout has occurred and exit the thread and possibly inform sqlserver that you're done (closing connection).
It's not easy, but it rarely is...
Edit 2:In your case, if you are unable to change the database code to asynchrone, make it a seperate process and kill that if neccesary. That way the resources (connection etc.) will be released. With threads, this won't be the case. But it's an ugly hack.
Edit 3:
You should use the BeginExecuteReader/EndExecuteReader Pattern.
this article is a good reference:
It will require rewriting your data access code, but it's the way to do it properly.

I get the feeling that giving the Thread 1000ms to abort is simply not enough. MSDN recommends that you call Thread.Join. It would definitely be helpful to see the code that is being aborted.
Thread.Abort
The thread is not guaranteed to abort
immediately, or at all. This situation
can occur if a thread does an
unbounded amount of computation in the
finally blocks that are called as part
of the abort procedure, thereby
indefinitely delaying the abort. To
wait until a thread has aborted, you
can call the Join method on the thread
after calling the Abort method, but
there is no guarantee the wait will
end.

What are you passing into your KillThread method? The cancel button will be being clicked on the UI thread, not the one that you want to kill.

You should signal your event when the user clicks Cancel (not kill the thread). In your example, the ManualResetEvent "mre"'s scope should be outside the thread function.

To answer the more general question of how to force kill any kind of Thread in C#:
If any unhandled Exception is thrown inside a thread (including those used by Task and other ways of running asynchronously), this thread will be terminated.
However note that this comes with many problems, like resources not being freed, improper memory management, general undefined behavior etc, and the unhandled Exception may still have to be handled by its parent thread (wherever it was started from) OR by registering for the following Event beforehand, depending on how the thread was started:
AppDomain.CurrentDomain.UnhandledException += YourEventHandler;
I should emphasize again that this should be an absolute last resort. If you need this, your applications is almost certainly designed poorly and there are probably different solutions you should use. There are good reasons why Thread.Abort is now deprecated and no longer functional.

Related

What happens when async code attempts to resume on a thread that is already executing?

I feel that the answer to this is due to me having an incorrect concept of how threads work, but here goes.
private void button1_Click(object sender, EventArgs e)
{
this.TestMethodAsync(); // No await, i.e. fire and forget
// ** Some code here to perform long running calculation (1) **
}
private async Task TestMethodAsync()
{
// Some synchronous stuff
await Task.Delay(1000);
// ** Some code here to perform long running calculation (2) **
}
First of all, I would not "fire and forget" an asynchronous method like this (I would use Task.Run) but I've come across code that does, and I'm trying to understand what the effect is.
In a WinForms application, which uses a WindowsFormsSynchronizationContext, my understanding of async and await tells me that when I click button1, the method will start synchronously on the UI thread. It will call TestMethodAsync and run synchronously until it reaches the await. It will then capture the context, start the Task.Delay task, and yield control to the caller. Since we are not awaiting this call, button1_Click will continue on the UI thread and start performing calculation (1).
At some point, Task.Delay(1000) will complete. A continuation will then run the remainder of the TestMethodAsync method using the captured context, which in this case means that the continuation will be run on the UI thread. This will now start performing calculation (2).
We now have two separate sections of code wanting to run on the same thread (the UI thread) at the same time. My investigations into this seem to suggest that the thread switches back and forth between the two sections of code in order to perform them both.
QUESTION:
I'm confused about exactly what is going on here. How is it possible to resume on a thread that is already running other code? What forces the thread to switch between the two sections of code that want to run? In general, what happens when you attempt to resume on a thread that is already running some other code?
(I suppose this isn't any different to how my click event runs on the UI thread in the first place, in as much as I know it runs on the UI thread, and I know the UI thread is also doing other stuff, but I've not really thought about it like this before.)
This is the secret that you do not understand: I give you the Windows Message Loop
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
BOOL bRet;
while(TRUE)
{
bRet = GetMessage(&msg, NULL, 0, 0);
if (bRet <= 0) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
This is the actual "main" of your application; you just don't see it because it is hidden behind the scenes.
A simpler loop could not be imagined. It gets a message from the queue. If there are no more messages then the program must be done. If there was a message then it runs the standard message translations and dispatches the message, and then keeps on running.
How is it possible to resume on a thread that is already running other code?
It isn't. "Resuming on a thread that is running other code" is actually putting a message in the queue. That "other code" is being synchronously called by DispatchMessage. When it is done, it returns to the loop, the queue is polled, and the message indicates what code needs to be dispatched next. That then runs synchronously until it returns back to the loop.
What forces the thread to switch between the two sections of code that want to run?
Nothing. That doesn't happen.
In general, what happens when you attempt to resume on a thread that is already running some other code?
The message that describes what continuation needs to be run is queued up.
I suppose this isn't any different to how my click event runs on the UI thread in the first place, in as much as I know it runs on the UI thread, and I know the UI thread is also doing other stuff, but I've not really thought about it like this before.
Start thinking about it.
Click events are exactly the same. Your program is doing something; you click the mouse; the click hander does not interrupt the UI thread and start running new work on it. Rather, the message is queued up, and when your UI thread control returns to the message loop, the click is eventually processed; DispatchMessage causes Button1_OnClick to be invoked via some mechanism in Windows Forms. That's what WinForms is; a mechanism for translating Windows messages into calls to C# methods.
But you already knew that. You know that when an event-driven program does a long-running synchronous operation, that the UI freezes, but that click events are processed eventually. How did you think that happened? You must have understood at some level that they were being queued up for processing later, right?
Exercise: What does DoEvents do?
Exercise: Given what you now know: what could possibly go wrong if you call DoEvents in a loop to unblock your UI?
Exercise: How is await different from DoEvents in a GUI application?
How is it possible to resume on a thread that is already running other code?
It needs to be specifically designed to support it. There needs to be some framework in place that allows the thread to take in work and to then execute that work at some later point in time.
This is how your UI thread works. It has a queue, and whenever you schedule work to be done in the UI thread you add an item to the end of the queue. The UI thread then takes the first item from the queue, executes it, and then when it's done, goes on to the next item, and so on, until you end your application.
What forces the thread to switch between the two sections of code that want to run?
Nothing, because it doesn't do that. It runs one, then when it finishes, it runs the other.
In general, what happens when you attempt to resume on a thread that is already running some other code?
Either someone wrote some custom code to specifically do just that, in which case, it does whatever that code specifically told it to do, or else you can't.

Thread Termination suggestion required

I am using BackgroundWorker for processing a long running external operation. However the user have option to cancel the background operation. Since my custom BackgroundWorker supports Thread.Abort(), all I am doing is BackgroundWorker.Abort() when user triggers Cancel from main thread.
But the thread is not actually terminating, it is still completing the external process. Is there any way I can terminate a thread instantly.
I do not have control on the external processing, so cannot send any flag for approach like while (checkThreadCancelled){}.
Below is my pseudo code.
Any help?
AbortableBackgroundWorker _bgWorker;
void MainThreadFunc()
{
_bgWorker = new AbortableBackgroundWorker();
_bgWorker.DoWork += new DoWorkEventHandler(bg_DoWork);
_bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler
( bg_RunWorkerCompleted );
_bgWorker.WorkerSupportsCancellation = true;
_bgWorker.RunWorkerAsync();
}
void bg_DoWork()
{
//Call external dll function for processing
}
void bg_RunWorkerCompleted()
{
//Process completed code
}
void CancelBgProcess()
{
if(_bgWorker != null)
_bgWorker.Abort();
}
The Abort method relies on worker thread cooperating with it. Ultimately it causes the CLR to throw an exception indicating that the thread is to abort, which the thread is free to deal with as it pleases.
As your worker thread is executing something in a DLL, the CLR isn't in control and therefore it does not have the option to throw an exception.
You have the option of using the Win32 TerminateThread API, but doing so is severe and may or may not lead to corruption within your process. TerminateThread is not really an option that you should ever choose.
Since you cannot modify the library that you are calling, you are left with two options. The first and easiest approach, lower the priority of the background thread and ignore the fact that it continues to run after cancellation.
The second is to launch your background operation in a separate process rather than thread. At which point, you may terminate the entire process if the operation is cancelled. If you go this route, you will need to pick some form of IPC to communicate the input and output parameters of the library.
Tasks and CancellationTokens ultimately will not help you in this situation as you will end up in the same place: executing library code that will not cooperate with you in order to be cancelled.
You don't want to use Thread.Abort, it is typically considered bad practice. There are many questions asked on SO that provide some very good explanations. For example: Timeout Pattern - How bad is Thread.Abort really?
Try looking at Tasks and CancellationTokens. See this MSDN article: http://msdn.microsoft.com/en-us/library/dd997396.aspx
Try this:
if (_bgWorker.IsBusy)
{
_bgWorker.WorkerSupportsCancellation = true;
//To cancel the Thread if Closing the Application
//while the Background Thread Worker is Still running on Background.
_bgWorker.CancelAsync();
}
It will stop the current thread process and will cancel the ongoing operation on that thread.
May be it helps you

stopping my thread

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();

Thread doesn't terminate when main thread finishes

I have a weird issue:
In my C# app, I am creating another thread, like so:
Thread printThread = new Thread(printWorker);
printThread.Name = "Logger MainThread";
printThread.IsBackground = true;
printThread.Start();
When my main thread finishes, this new thread just keeps on working, although it's marked as Background.
What could be the causes for this?
This object is holding a Mutex object, not sure this may be the reason...
Any ideas anyone?
Here's the code from the printWorker method:
while (loggerIsActive)
{
LogMessage log = LoggerQueue.Dequeue();
if (log.message != null)
{
syncLogObj.WaitOne();
lock (writerobj)
{
StreamWriter sw;
if (!File.Exists(fName))
{
sw = File.CreateText(fName);
}
else
{
sw = new StreamWriter(fName, true);
}
using (sw)
{
if (log.message != "")
{
if (log.message.EndsWith("\r\n"))
{
log.message =
log.message.Substring(0, log.message.Length - 2);
}
sw.WriteLine(string.Format("[{0}][{3}][{1}] | {2}",
log.msgTime,
log.level.ToString(),
log.message,
log.sender.ToString()));
}
sw.Flush();
sw.Close();
}
}
syncLogObj.ReleaseMutex();
}
Thread.Sleep(5);
}
Try this:
Start the app through VS and exit normally. The VS should stay in Debug mode as you described. Click on Pause button (Break all) and then go to Debug->Windows->Threads. Do you see your "Logger MainThread" in the list?
If so, double-click it, it should lead you to the code line that the thread is currently executing. Step-debug from there and see why is it not terminating.
If you don't see it try looking at other threads that have not terminated and try to find the problem.
Otherwise, with those kind of problems it's always useful to monitor the program state via System.Diagnostics.Debug.Print statements (you can see them printing in the VS output window).
kill it.
Not pretty. But this isn't TV. Read on:
1) Not sure you use are using it but it appears you should be locking loggerqueue before you queue(main pgm) or dequeue(thread).
2) No need to lock writerobj with just this setting. But really you should so you can safely kill the thread not during a write:
main thread:
do everything
before close:
-lock writerobj
-printthread.abort
worker thread:
add try catch to handle threadabort exception and just quit
If you're properly doing this, you shouldn't have to use Waits and mutexes. If you are using wait properly anyway you won't need the sleep.
General advice for this application: why not log on main thread? if your logging is that busy, log results will be pretty useless.
But there are rare cases where that might be wrong. Entonces......
General advice to have threads play nice for this problem:
Main program
encapsulate logging (notably, quit flag, queue, and worker thread ref) in an object
'global snobs?' Logging is a rare excuse to use singleton patter.
start worker thread in logger object via method
main thread always calls a single method on logger object to log error
That method locks the queue and adds to it.
Use Monitor/Pulse/Wait, no sleep; full examples abound; it is worth learning
because only this thread is hitting the file anyway, unless you have multiple processes, you don't need waitone/releasemutex.
That logging method monitor.pulses an object
That frees the worker thread's monitor.wait (which is what idles the CPU instead of sleep)
lock the queue, only inside the lock dequeue the object to local ref; nothing else.
Do your normal logging code and 'exit check' loop. Add
Your logic code could leave message unwritten if queue is full on quit:
change to exit check so you can do it without an extra lock of queue:
move declaration of queued object refernce above while; set it to nothing
change logic in while to 'loggerisactive or log != null'
when your main thread finishes, in your exit code:
set the quit flag
pulse the object you're using to wait incase it's not processing the queue
Thread will fall thru.
You have a lot of stuff going on that you're obviously not showing...
Exmaple: you have syncLogObj.WaitOne();, but we don't see where syncLogObj is being declared, or used elsewhere in your program.
Plus, you don't need it... get rid of the syncLogObj thing altogether (including the "ReleaseMutex" garbage)... you already have a lock (blah) { }, and that's all you need (from what code you have displayed).
It's likely that the main thread is NOT ending, likely because of this or some other object that is keeping it open.
So, simple instructions
Get rid of syncLogObj (because you already have the "lock")
Make sure you set loggerIsActive = false somewhere.
Edit: Even more details!
From what I see - you don't need the lock (writerobj) at all, because (I'm quite sure), you only seem to have one thread that is writing to the log.
The "lock" is only there if you have two or more threads that running that code (basically).
If printworker does not finish before your main thread is done, then main will die and your printworker thread will be killed by the OS. If you want main to wait for the thread you created, then you should call printThread.Join() in main. That will get main to wait on your thread.
When main finishes your program dies and your printThread will be destroyed by the OS, It will not keep running.
From here
Background threads are identical to
foreground threads with one exception:
a background thread does not keep the
managed execution environment running.
Once all foreground threads have been
stopped in a managed process (where
the .exe file is a managed assembly),
the system stops all background
threads and shuts down.
Tony the Tiger has the right idea but additional code needs to be added to kill the thread before the application closes.
printThread.Join(1000);
if(printThread!=null && printThread.IsAlive)
printThread.Abort();
Thread.Abort();
Thread.Dispose();
That should do it if I'm not mistaken.

Thread does not abort on application closing

I have an application which does some background task (network listening & reading) in a separate Thread. It seems however that the Thread is not being Terminated/Aborted when I close the application (click "x" button on titlebar).
Is that because the main Thread routine is while(true) {...} ?
What is the solution here? I was looking for some "interruption" flag for the Thread as the condition for "while" loop, but didn't found any.
The simplest way is to set the IsBackground property of the thread to true. This will prevent it from keeping the application open. An application terminates when all non-background threads terminate.
A more controlled way to stop the thread is to send it a message to shut down cleanly and ensure that it has terminated before letting your main thread terminate.
A method that I wouldn't recommend is to call Thread.Abort. This has a number of problems, one of which is that it is not guaranteed to terminate the thread. From the documentation:
Calling this method usually terminates the thread.
Emphasis mine.
You can always force the issue:
class Program
{
public static void Main()
{
// ... do stuff
Environment.Exit(Environment.ExitCode);
}
}
The better approach is to set the Thread.IsBackground property to true as Mark already mentioned.
You could improve the while(true) loop to
void DoWork() {
while(!ShouldIQuitManualResetEvent.WaitOne(0)) {
// do something
}
IDidQuitManualResetEvent.Set()
}
A bit more graceful, short from the identifier names.
Well, instead of while(true), maybe you should:
while(appIsRunning)
{
}
And, at the closing event for your form,
appIsRunning = false;
thread.Join(2000);
where the last line is just to make sure you wait for the thread to cleanly finish. There are many other ways to force an end to a thread, but the problem is just there: you don't want to be forcing things, you want them to happen as naturally as possible.
After the join, you can check the status of thread to see if it has finished. If it doesn't, then (and only then) force its finish with a abort, and maybe notify your user (or write a log record) that something has not ended the way it should.
You can start your thread as:
ThreadPool.QueueUserWorkItem(DoStuff, input)
And it will be abort automatically with application close.

Categories

Resources