Thread doesn't terminate when main thread finishes - c#

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.

Related

C# finding managed thread

I'm using the System.Threading.Thread object to create a background-working method. The method loads data which can also be used by the user in the current time (must be read from the same source). That's why I'd like to find the created Thread and pause it for the time of current data-loading.
Here comes the problem... How to find the Thread?
I've already read about System.Diagnostics.Process attempt, but it contains data only about the OS-Threads.
Also I need to say that the method starting the Thread is static and it's possible but really unwanted to create an object to track the thread. I'm just creating new object and starting it...
(new Thread(new ThreadStart(...))).Start();
I've looked through many topic but I found no following question:
IF IT'S IMPOSSIBLE, THAN FROM WHERE THE VISUAL STUDIO -> THREAD WINDOW TAKES INFORMATION!?
Thanks in advance for any help :)
If pausing the "reading" thread is truly required, you can have it wait for a signal using the EventWaitHandle class, set as Manual or Automatic reset depending on your use case, starting unset. The background thread, when it has finished writing to whatever the shared variable location is, can set the signal on the wait handle to release the "reading" thread that was stuck waiting.
If your "reading" thread only needs to pause sometimes, you can use the same wait handle approach, except have it start as "set" in Manual Reset mode while your "reading" thread checks it whenever appropriate. The "reading" thread will skip over waiting for the signal (because it's already set)!
Once your "writing" thread needs to make a change, it would reset the wait handle, causing your "reading" thread to pause when it checks for the signal, update the data, then "set" the signal again to release the paused "reading" thread.
Use Task for background work and you can utilize Continue method to process the data on completion of task.
var task = Task.Run(() => "Test");
task.ContinueWith((str) => "Process data");
Or utilize Name property of Thread class to assign the name.

Thread "hanging" on Monitor.Wait after Application.Current.ShutDown()

I have a WPF application which used to shutdown via Environment.Exit. Since this caused problems with my automated UI tests, I changed the exiting application to Application.Current.ShutDown.
This works fine, except there is a thread which is waiting to be pulsed (Monitor.Wait), which keeps the process running since it never gets pulsed anymore.
I thought that would be a no brainer to fix, but from the point where my application exits (the Application.Current.ShutDown) it's rather hard to retrieve a reference to the object which holds the waiting thread (in order to force pulse it, so that it can exit).
I tried to google an appropriate answer, but not much luck yet. Is there an "easy way" out of this? Or should I start refactoring already? :)
Some snippets:
Thread is created like this
workerThread = new Thread(Worker) { Name = logName, IsBackground = true};
In the Worker method, Monitor.Wait is called
while ((action = GetNextTask(out task)) == ProductPreparationAction.None)
{
Monitor.Wait(preparationTasks);
}
Nevermind my comment. Start refactoring :).
First of all, there should be a way for the while loop to end when before the app stops. Perhaps you can use and propagate a CancellationToken all the way down to the Worker method.
If you want to keep your loose coupling, you should be able to pulse by creating an event in the class that calls Application.Current.ShutDown and by subscribing to it in the class where the Worker method is (and call Pulse in the event handler).
If you do this, then you can store the CancellationToken in this class and flag it when the event is received.
That event should be raised before calling Application.Current.ShutDown.

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

How to Kill a C# Thread?

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.

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