I am not trying to beat a dead horse, honestly. And I've read all the advice on thread killing, however, please consider the code. It does the following:
It starts a thread (via StartThread method)
It calls the database looking for anything in the ServiceBroker queue. Note the WAITFOR command - it means that it will sit there until there is something in the queue. All this in MonitorQueue method.
Kill the thread. I tried .Interrupt - it seems to do absolutely nothing. Then I tried .Abort, which should never be used, but even that did nothing.
Thread thxMonitor = new Thread(MonitorQueue);
void StartThread() {
thxMonitor.Start();
}
void MonitorQueue(object obj) {
var conn = new SqlConnection(connString);
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandTimeout = 0; // forever and ever
cmd.CommandType = CommandType.Text;
cmd.CommandText = "WAITFOR (RECEIVE CONVERT(int, message_body) AS Message FROM SBQ)";
var dataTable = new DataTable();
var da = new SqlDataAdapter(command);
da.Fill(dataTable);
da.Dispose();
}
void KillThreadByAnyMeansNecessary() {
thxMonitor.Interrupt();
thxMonitor.Abort();
}
Is it actually possible to kill a thread?
Set an Abort flag to tell the thread is needs to terminate. Append a dummy record to the ServiceBroker queue. The WAITFOR then returns. The thread then checks its 'Abort' flag and, finding it set, deletes the dummy record from the queue and exits.
Another variant would be to add a 'real' poison-pill record to the specification for the table monitored by the ServiceBroker - an illegal record-number, or the like. That would avoid touching the thread/s at all in any direct manner - always a good thing:) This might be more complex, especially if each work thread is expeceted to notify upon actual termination, but would still be effective if the work threads, ServiceBroker and DB were all on different boxes. I added this as an edit because, having thought a bit more about it, it seems more flexible, after all, if the threads normally only communicate via. the DB, why not shut them down with only the DB? No Abort(), no Interrupt() and, hopefully, no lockup-generating Join().
I hate to not answer your question, but consider going about this a different way. T-SQL allows a TIMEOUT parameter to be specified with WAITFOR, such that if a message is not received in a certain period of time, the statement will quit and have to be tried again. You see this over and over again in patterns where you have to wait. The tradeoff is that you don't immediately get the thread to die when requested -- you have to wait for your timeout to expire before your thread dies.
The quicker you want this to happen, the smaller your timeout interval. Want it to happen instantly? Then you should be polling instead.
static bool _quit = false;
Thread thxMonitor = new Thread(MonitorQueue);
void StartThread() {
thxMonitor.Start();
}
void MonitorQueue(object obj) {
var conn = new SqlConnection(connString);
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "WAITFOR (RECEIVE CONVERT(int, message_body) AS Message FROM SBQ) TIMEOUT 500";
var dataTable = new DataTable();
while(!quit && !dataTable.AsEnumerable().Any()) {
using (var da = new SqlDataAdapter(command)) {
da.Fill(dataTable);
}
}
}
void KillThreadByAnyMeansNecessary() {
_quit = true;
}
EDIT:
Although this can feel like polling the queue, it's not really. When you poll, you're actively checking something, and then you're waiting to avoid a "spinning" condition where you're constantly burning up CPU (though sometimes you don't even wait).
Consider what happens in a polling scenario when you check for entries, then wait 500ms. If nothing's in the queue and 200ms later a message arrives, you have to wait another 300ms when polling to get the message. With a timeout, if a message arrives 200ms into the timeout of the "wait" method, the message gets processed immediately.
That time delay forced by the wait when polling vs. a constant high CPU when polling in a tight loop is why polling is often unsatisfactory. Waiting with a timeout has no such disadvantages -- the only tradeoff is you have to wait for your timeout to expire before your thread can die.
Don't do this! Seriously!
The function that you need to call to kill a thread is the TerminateThread function, which you can call via P/Invoke. All the reasons as to why you shouldn't use this method are right there in the documentation
TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you
know exactly what the target thread is doing, and you control all of
the code that the target thread could possibly be running at the time
of the termination. For example, TerminateThread can result in the
following problems:
If the target thread owns a critical section, the critical section will not be released.
If the target thread is allocating memory from the heap, the heap lock will not be released.
If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be
inconsistent.
If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other
users of the DLL.
The important thing to note is the bit in bold, and the fact that under the CLR / .Net framework you are never in the situation where you know exactly what the target thread is doing (unless you happen to write the CLR).
To clarify, calling TerminateThread on a thread running .Net code could quite possibly deadlock your process or otherwise leave in a completely unrecoverable state.
If you can't find some way to abort the connection then you are far better off just leaving that thread running in the background than trying to kill it with TerminateThread. Other people have already posted alternative suggestions on how to achieve this.
The Thread.Abort method is slightly safer in that it raises a ThreadAbortException rather than immediately tearing down your thread, however this has the disadvantage of not always working - the CLR can only throw the exception if the CLR is actually running code on that thread, however in this case the thread is probably sat waiting for some IO request to complete in native SQL Server Client code instead, which is why your call to Thread.Abort isn't doing anything, and won't do anything until control is returned to the CLR.
Thread.Abort also has its own problems anyway and is generally considered a bad thing to be doing, however it probably wont completely hose your process (although it still might, depending on what the code running is doing).
instead of killing your thread, change your code to use WAITFOR with a small timeout.
after the timeout elapses, check to see if the thread has been interrupted.
if not, loop back around and do your waitfor again.
Yes, "the entire point" of waitfor is to wait for something. But if you want something to be responsive, you can't ask one thread to wait for Infinity, and then expect it to listen to anything else.
It is not just easy to terminate the thread right away. There is a potential potential problem associated with it:
Your thread acquire a lock, and then you kill it before it releases the lock. Now the threads who require the lock will get stuck.
You can use some global variable to tell the thread to stop. You have to manually, in your thread code, check that global variable and return if you see it indicates you should stop.
Please refer to this question discussing the same thing:
How to kill a thread instantly in C#?
Related
I am trying this code to convert a document using aspose word, I am trying to terminate the process of conversion of document when it takes too long (as it leads to memory leak and eats up all system resources), I never looked at threading or async before, but now as our production server is broken I am looking for a quick fix before digging any deeper,
This is what I tried but it kills the thread but keeps all the resources, I read some posts from What's wrong with using Thread.Abort() but I am not sure what is the best way to move forward, should I use Task and async but I don't know how to use them in this context,
RunWithTimeout(() =>
{
status = AsposeConversion.ConvertToPDF(licensePath, fileName);
}, TimeSpan.FromMilliseconds(1000 * 60 * 4));
public static bool RunWithTimeout(ThreadStart threadStart, TimeSpan timeout)
{
Thread workerThread = new Thread(threadStart);
workerThread.Start();
bool finished = workerThread.Join(timeout);
if (!finished)
workerThread.Abort();
return finished;
}
Should I create a new process ? but then how can I timeout it or run conversion code line in it.
Edit
Sorry for confusion, I said it takes too long, but in real it never returns even for 4 hours I tested so far..
Since AsposeConversion.ConvertToPDF is a blocking method, you cannot send a signal to tell the thread to end gracefully, as the thread will not check the signal until the blocking method has completed.
All I can suggest is to let the thread run until AsposeConversion.ConvertToPDF returns, then check within thread if the maximum allowed time has passed, and if so clean up before terminating.
Edit - After knowing the method call does not return at all
It looks like this is an issue with Aspose, so you should find out why that method call is never returning and see if there is something you are doing wrong, or any workaround if it is a bug.
If you don't manage to make the method work as expected, as an extreme solution you could try to run the code inside a Job object. It will allow you to execute your code as a separate process and limit the memory the process can use. You can then handle the OutOfMemoryException and clean up as necessary.
It is horrible, I know, but will prevent your server from crashing while you wait for a workaround / bug fix.
I have created a timeout function based on things I have seen in various places but am pretty sure I am not doing it a great way! (But it does seem to work.)
I am connecting to a piece of hardware that if working connects in a few seconds but if not takes around 1 minute to timeout. So if I can create my own timeout function I can set it at 20 seconds and save lots of time and waiting.
I have tried to make it so my timeout returns a string:
static string CallWithTimeout(Action action, int timeoutMilliseconds)
{
string reply = "";
Thread threadToKill = null;
Action wrappedAction = () =>
{
threadToKill = Thread.CurrentThread;
action();
};
IAsyncResult result = wrappedAction.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds))
{
reply = "Connected";
wrappedAction.EndInvoke(result);
return reply;
}
else
{
threadToKill.Abort();
reply = "Error";
return reply;
}
}
then I call it with something like :
string replyfromreader = CallWithTimeout(connectToHardware, 20000);
the connectToHardware is just a one liner so no need to post.
It's okayish as far as .NET state is concerned. You won't call EndInvoke(), that leaks resources for 10 minutes, the default lifetime of remoted objects.
In a case like this, calling Thread.Abort() has a very small chance of succeeding. A managed thread needs to be in an alertable wait state to be abortable, it just never is when the thread is buried deep inside native code that ultimately waits for some device driver call to complete.
Leaving the CLR in a state where it keeps trying to abort a thread and never succeeds is not particularly pleasant, not something I've ever tried on purpose so no real idea what the side-effects are. It does however mean that your code will block on the Abort() method call so you still haven't fixed the problem. The best thing to do is therefore to not abort the thread but just abandon it. Setting a flag that marks the device dead so you don't try to do this ever again.
If you want to continue running your program, even without the device being in a usable state, and you want to provide a way to recover from the problem then you'll need an entirely different approach. You'll need to put the device related code in a separate process. Which you can then Kill() when the device is unresponsive, relying on Windows to clean up the shrapnel. Interop with that process using a low-level mechanism like named pipes or sockets is best so you can recover from the disconnect fairly easily.
Avoiding Thread.Abort is always a good idea. Avoiding it on a thread you did not create is even better.
Assuming if the hardware is not working, and you want the timeout, it does not matter if connectToHardware is left to timeout on its own and no error/exception details are wanted, then you can use the Task Parallel Library (TPL): System.Threading.Tasks.Task:
// True => worked, False => timeout
public static bool CallWithTimeout(Action method, TimeSpan timeout) {
Exception e;
Task worker = Task.Factory.StartNew(method)
.ContineueWith(t => {
// Ensure any exception is observed, is no-op if no exception.
// Using closure to help avoid this being optimised out.
e = t.Exception;
});
return worker.Wait(timeout);
}
(If the passed Action could interact with a passed CancellationToken this could be made cleaner, allowing the underlying method to fail quickly on timeout.)
i am trying to build a multi threaded server that is supposed to spawn new threads for every incoming connection, BUT for all my effort, it spawns new threads only when it feels like it, Can anybody help me debug this code? am i missing something obvious?
while (true)
{
if (txtAddress.Text.Trim() == "Any" || txtAddress.Text.Trim() == "any")
ipEndP = new IPEndPoint(IPAddress.Any, 778);
else
ipEndP = new IPEndPoint(IPAddress.Parse(txtAddress.Text.Trim()), 778);
tcpL = new TcpListener(ipEndP);
tcpL.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
tcpL.Start();
tempSock = tcpL.AcceptSocket();
//t = new Thread(ConnectionHandler); //When new client is connected, new thread //is created to handle the connection
//t.Priority = ThreadPriority.Highest;
//t.Start(tempSock);
ThreadPool.QueueUserWorkItem(ConnectionHandler, tempSock);
}
Check out the MSDN docs for QueueUserWorkItem
Queues a method for execution. The method executes when a thread pool thread becomes available.
Placing a thread in the user work item queue does not guarantee that it will begin executing right away. That's actually a good thing. If you got so many connections that you needed hundreds or thousands of threads, that could easily bring your server to it's knees (and certainly would be very wasteful due to excessive context switches).
Your commented out code should kick off a new thread for every connection. Is that not working? If so, what exactly is not working? Note that creating a new thread for every connection is much more expensive than using the thread pool.
UPDATE
Based on your remark that the commented out code is also failing to create too many threads, I would add...
You are creating WAY too many threads if that happens.
Often I see people asking why they can't create more than around 2000 threads in a process. The reason is not that there is any particular limit inherent in Windows. Rather, the programmer failed to take into account the amount of address space each thread uses.
A thread consists of some memory in kernel mode (kernel stacks and object management), some memory in user mode (the thread environment block, thread-local storage, that sort of thing), plus its stack. (Or stacks if you're on an Itanium system.)
Usually, the limiting factor is the stack size.
http://blogs.msdn.com/b/oldnewthing/archive/2005/07/29/444912.aspx
If I need to cancel some operation on a thread, when should I use Thread.Abort vs Thread.Interrupt. I read the documentation on it but not sure which scneario should i use a particular call between two.
If there is any third way of doing it, please let me knwo about it too with pro and cons.
I would avoid using Thread.Abort at all costs. Its behavior is much safer and predictable since .NET 2.0, but there are still some pretty serious pitfalls with it. Most of the aborts inside managed code can be made safe, but not all of them. For example, I believe there are some subtle problems if an abort request is triggered during the processing of a static constructor. Nevermind, the fact that the out-of-band exception can occur at anytime giving you little control over defining where the safe points for shutdown are located.
There are several acceptable ways to terminate a thread gracefully.
Use Thread.Interrupt
Poll a stopping flag
Use WaitHandle events
Specialized API calls
I discuss these methods in my answer here.
Most suggestions are already done, but here's an example how i would do it:
ManualResetEvent _requestTermination = new ManualResetEvent(false);
Thread _thread;
public void Init()
{
_thread = new Thread(() =>
{
while (!_requestTermination.WaitOne(0))
{
// do something usefull
}
}));
_thread.Start();
}
public void Dispose()
{
_requestTermination.Set();
// you could enter a maximum wait time in the Join(...)
_thread.Join();
}
This way the dispose will wait until the thread has exited.
If you need a delay within the thread, you shouldn't add Thread.Sleep.
Use the WaitOne(delayTime). This way you will never have to wait to terminate it.
I wouldn't use Thread.Abort ever. It causes an exception at an almost arbitrary time.
Be careful with Thread.Interrupt. If you don't build in some waiting or sleeping time the thread won't be interrupted.
Be careful with Thread.Abort. If you catch the ThreadAbortException your thread will terminate right after catch + finally.
(I like to use those methods to send a signal to my thread so that it knows it's terminating time, then clean up and exit.)
I am creating an array of threads based on the number of records in a database. Each thread then polls an ipaddress and then sleeps for a time and then repolls again. I periodically check the database for any change in the number of hosts. If there are more hosts I start another thread. If there are less hosts I need to kill the specific thread that was monitoring that host. How do i kill the specific thread.
enter code here protected static void GetThreads()
{
Thread[] threads;
do
{
dt = getIP_Poll_status();
threads = new Thread[dt.Rows.Count];
Console.WriteLine(dt.Rows.Count + " Threads");
for (int i = 0; i < threads.Length; ++i)
{
string ip = dt.Rows[i][0].ToString();
int sleep = Convert.ToInt32(dt.Rows[i][1].ToString());
string status = dt.Rows[i][2].ToString();
string host = dt.Rows[i][3].ToString();
Hosts.Add(host);
string port = dt.Rows[i][4].ToString();
//Console.WriteLine("starting on " + ip + " delay " + sleep+".current status "+status);
threads[i] = new Thread(PollingThreadStart);
threads[i].Start(new MyThreadParameters(ip, sleep, status, host, port));
threads[i].Name = host;
}
Thread.Sleep(50000);
}
while (true);
}
Killing threads forcibly is a bad idea. It can leave the system in an indeterminate state.
You should set a flag (in a thread-safe way) so that the thread will terminate itself appropriately next time it checks. See my threading article for more details and sample code.
I would add that using Sleep is almost always the wrong thing to do, by the way. You should use something which allows for a graceful wake-up, such as Monitor.Wait. That way when there are changes (e.g. the polling thread should die) something can wake the thread up if it's waiting, and it can notice the change immediately.
Given that most of your threads will spend the majority of their time doing nothing, your design might be better realised as a single thread that keeps a list of ip addresses and the time they're due to be polled next. Keep it sorted in order of next poll time.
Pseudocode:
What time does the next ip address need to be polled?
Sleep till then
Poll the address.
Update the poll time for that address to now + interval.
Resort the list
Repeat.
Whenever you have a DB update, update the list and then order the thread to re-evaluate when it needs to stop.
You don't specify the language you are targetting, but in general you use the same method regardless of the language. Simple use a shared variable that is used to signal the thread when it is time to stop running. The thread should periodically check the value and if it is set it will stop in a graceful fashion. Typically, this is the only safe method to stop a thread.
I would say:
Don't kill threads. Ask them to die, nicely (vie Events or some shared flag).
Be careful when creating exactly one thread per DB entry. This could mean that some unexpected DB activity where suddenly you have many rows translates into killing the OS with too many threads. Definitely have a limit on the number of threads.
You could send an interrupt signal to the thead you want to end. The thread that has been signalled would need to catch the ThreadInterruptedException that will be raised, and exit gracefully.
There are other, possibly better, ways to achieve what you want, but they are more complicated...
What you are trying to do is a bad idea because of the reasons mentioned above. However you can still give the thread a name which can be the host name. You may find out the thread by checking the name and kill it.