|
Thanks Le Centriste,
Le Centriste wrote: Yes, and if your thread is also prone to block, handle the ThreadInterruptedException also.
Either Abort or Interrupt is called, the Finalizers are not ensured to be called? I think if they are ensured to be called, we can rely on them to clean-up resources, and leave the body of handlers for Abort/Interrupt exceptions empty.
Any comments?
regards,
George
|
|
|
|
|
As a golden rule, you should always clean up behind you, and not rely on your mother to do it.
Seriously, you could simply use the using statement, as finally blocks are always executed, no matter what. That will free you from having to handle the exceptions and still do the cleanup.
We should not rely on the Finalizers, as they are there as a last defense, and you don't know when they execute. Calling the Dispose method from a finally is a surefire way of cleaning up.
|
|
|
|
|
Thanks Le Centriste,
I am just wondering whether there are any official documents from Microsoft about whether finally block or Finalizer will be ensured to be called, when we call Interrupt or Abort on thethread?
Do you find such documents?
regards,
George
|
|
|
|
|
George_George wrote: I think if they are ensured to be called, we can rely on them to clean-up resources, and leave the body of handlers for Abort/Interrupt exceptions empty.
You can't rely on the finalisers to be called. When the objects are up for dispose, they will be placed in the queue for finalising. A background thread calls the Finalize method of the objects, but if there are too many objects left in the queue when the application ends, the objects will just be thrown away without finalising.
The ThreadAbortException exception exists so that you will have a chance to clean up the resources properly, so that you don't have to hope that they will eventually clean up themselves. You should clean up the resources as soon as possible, not wait for the garbage collector to initiate the cleanup.
If you create the IDisposable objects in using blocks, they will be disposed properly even if the thread is aborted.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
1.
Guffa wrote: A background thread calls the Finalize method of the objects, but if there are too many objects left in the queue when the application ends, the objects will just be thrown away without finalising.
Is the above scenario documented as a defined behavior for GC? I am confused. In my understanding, no matter how many objects need to get Finalize method called, they are all ensured to be called.
Do you have any documents to support your points that in some situations, the finalizers can not called?
2.
Guffa wrote: The ThreadAbortException exception exists so that you will have a chance to clean up the resources properly, so that you don't have to hope that they will eventually clean up themselves. You should clean up the resources as soon as possible, not wait for the garbage collector to initiate the cleanup.
Clean-up in the handler for ThreadAbortException?
regards,
George
|
|
|
|
|
George_George wrote: Do you have any documents to support your points that in some situations, the finalizers can not called?
"A stalled finalizer can prevent the CLR from completing the AppDomain tear down. To account for this, the CLR implements a timeout on this process, after which it will stop the finalization process."
Identify And Prevent Memory Leaks In Managed Code[^]
"Finalizers are expensive to run, and there’s no order (or even guarantee) that they will be run (for example, the finalizer thread may time out, or be killed on AppDomain unload)."
Demystifying Dispose[^]
"if the process is terminating, the system will timeout the finalizer thread if it cannot finalize all the items in a reasonable amount of time."
Critical finalizers (reliability part 1)[^]
".Net doesn't make any guarantee that the finalizer for each object will get called. In the current implementation .Net has one finalizer thread. If there exist a finalizer which block this thread then the other finalizer will never get called"
Memory Leak Detection in .Net[^]
George_George wrote: Clean-up in the handler for ThreadAbortException?
Yes, for anything that you can't use a using or try...finally to clean up.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
You are so knowledgable. Two more questions,
1.
Seems we can not rely on Finalizer when thread is Aborted.
Can we rely on finally block and exception handler for ThreadAbortException?
2.
Seems the timeout issue for Finalizer (Finalizer can not execute longer than some amount of time, as your referred article describes) only happens when AppDomain shuts down. If the AppDomain is still running, there should not be timeout issue?
regards,
George
|
|
|
|
|
George_George wrote: Can we rely on finally block and exception handler for ThreadAbortException?
A using block is the best way to ensure that objects are disposed. A try...finally works just as fine, assuming that you implement it correctly. The ThreadAbortException is sure to occur if the thread is aborted, but as it can happen anywhere in the code, it's a lot trickier to implement correctly.
George_George wrote: Seems the timeout issue for Finalizer (Finalizer can not execute longer than some amount of time, as your referred article describes) only happens when AppDomain shuts down. If the AppDomain is still running, there should not be timeout issue?
There could be, if one finaliser doesn't return. I'm not sure how the finilising thread handles this, but either it locks up, or it times out that specific finalisation after a while. Even if it has a timeout for every finalisation, it migh be busy for a very long time if there are a lot of instances of the same class, where the finaliser doesn't work.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Cool, Guffa!
I am just curious that why there is no documents which we could find that expected finally blocks and exception handler block are ensured to be executed during ThreadAbortException?
regards,
George
|
|
|
|
|
There is no specific documentation about this, because it's not handled any different than in any other code.
The only thing that is special is that the ThreadAbortException is thrown whenever the thread is aborted, and (AFAIK) that the exception doesn't cause a ThreadException in the application, if the thread doesn't catch it. Other than that, the situation is handled just as with any other exception.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
Suppose I have ThreadAbortException in a worker thread, the main thread could only catch it by using AppDomain.CurrentDomain.UnhandledException?
regards,
George
|
|
|
|
|
George_George wrote: Suppose I have ThreadAbortException in a worker thread, the main thread could only catch it by using AppDomain.CurrentDomain.UnhandledException?
Yes, that would be the only way of catching an exception from outside the thread. However, I don't think that a ThreadAbortException exception will cause that event to be triggered, but I can't find any documentation right now that either confirms or contradicts this.
A couple of clarifications/additions that I found while reading about the ThreadAbortException:
There is one more thing that is special about the ThreadAbortExcpetion; it will automatically be rethrown even when caught. So, it will trigger any matching catch all the way up the stack, unless Thread.ResetAbort is called to stop it from being rethrown.
The ThreadAbortException exception can be used by the thread to catch when the application is aborting the thread, but if a background thread is aborted because the application is ending, the exception will not be thrown.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
1.
Guffa wrote: Yes, that would be the only way of catching an exception from outside the thread. However, I don't think that a ThreadAbortException exception will cause that event to be triggered, but I can't find any documentation right now that either confirms or contradicts this.
I have verified you are correct. Here is my code. Could you review whether my code is correct please?
using System;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void ThreadProc()
{
Console.WriteLine("Begin sleeping ");
Thread.Sleep(5000);
Console.WriteLine("End sleeping ");
}
static void Foo(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("I am here ");
}
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(Foo);
Thread t = new Thread(Program.ThreadProc);
t.Start();
t.Abort();
return;
}
}
}
2.
Guffa wrote: but if a background thread is aborted because the application is ending, the exception will not be thrown.
Confused. You mean the ThreadAbortException will not be re-throw if it is caught?
regards,
George
|
|
|
|
|
George_George wrote: I have verified you are correct. Here is my code. Could you review whether my code is correct please?
Yes, that is correct as far as I can see.
George_George wrote: Confused. You mean the ThreadAbortException will not be re-throw if it is caught?
No, I mean that the ThreadAbortException will not be thrown at all. The background threads will just be stopped.
From the documentation of the Thead.IsBackground property:
"Once all foreground threads belonging to a process have terminated, the common language runtime ends the process. Any remaining background threads are stopped and do not complete."
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
Guffa wrote: No, I mean that the ThreadAbortException will not be thrown at all.
I have verified that ThreadAbortException will be thrown, here is my code. Please review whether my code is correct.
In my test in VS 2008, the lines, will be executed, means ThreadAbortException will be thrown,
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
using System;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void ThreadProc()
{
try
{
Console.WriteLine("Begin sleeping ");
Thread.Sleep(5000);
Console.WriteLine("End sleeping ");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
static void Foo(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("I am here ");
}
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(Foo);
Thread t = new Thread(Program.ThreadProc);
t.IsBackground = true;
t.Start();
Thread.Sleep(1000);
t.Abort();
Console.WriteLine("I am there ");
return;
}
}
}
regards,
George
|
|
|
|
|
Yes, of course it will be thrown if you abort the thread.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
This is what you mentioned before.
--------------------
No, I mean that the ThreadAbortException will not be thrown at all. The background threads will just be stopped.
--------------------
I do not think there is any differences dealing with Thread.Abort a background thread and a normal thread. If you think there are any differences, could you post your code or describe your ideas in more details please (so that I can write some test code to learn from you)?
regards,
George
|
|
|
|
|
George_George wrote: I do not think there is any differences dealing with Thread.Abort a background thread and a normal thread.
That's correct.
If you look at the quote in context, you will see that I was talking about what happens to the threads when the application ends.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
Question answered.
regards,
George
|
|
|
|
|
Hello everyone,
About using Abort or Interrrupt to stop a thread, I have two questions.
1. What are the pros and cons about Abort v.s. Interrupt?
2. If I program a background thread, compared with normal thread, will there be any special points to take care of (e.g. code in different) if the thread is stopped with Abort (or Interrupt)?
thanks in advance,
George
|
|
|
|
|
An excellent tutorial here[^].
SkyWalker
|
|
|
|
|
Thanks Mircea,
Actually, this is the question when I read the famous tutorial.
But no direct answer from the tutorial. Do you have any ideas?
regards,
George
|
|
|
|
|
A blocked thread can be released prematurely in one of two ways:
- through Thread.Interrupt;
- through Thread.Abort.
1) This will happen through the activity of another thread.
Interrupting a thread only releases it from its current/next) wait.
It doesn't cause the thread to end (unless the ThreadInterruptedException is unhandled).
If Interrupt is called on a thread that’s not blocked, the thread continues executing until it next blocks. At that point a ThreadInterruptedException is thrown.
Interrupting a thread arbitrarily is dangerous as the framework or some third-party methods in the calling stack could unexpectedly receive the interrupt rather than your intended code. All it would take is for the thread to block briefly on a simple lock or synchronization resource, and any pending interruption would kick in. If the method wasn't designed to be interrupted (with appropriate cleanup code in finally blocks) some objects may be left in an unusable state, or there may be resources incompletely released.
2) A blocked thread can also be released via its Abort method. This would lead to a similar effect like in the case of calling Interrupt , excepting that a ThreadAbortException is thrown instead of a ThreadInterruptedException . And one more thing here: the exception will be re-thrown at the end of the catch block (in an attempt to terminate the thread for ever) unless Thread.ResetAbort is called within the catch block.
The main difference between Interrupt and Abort concerns what happens when each of them is called on a thread that is not blocked. While Interrupt waits until the thread next blocks before doing anything, Abort throws an exception on the thread right where it's executing.
SkyWalker
|
|
|
|
|
Thanks Mircea,
Two more questions,
1. When using Interrupt method, we need to consider whether thread is in wait status. I am wondering if,
- the thread is executing and waiting on lock (someobject), e.g. blocked on lock statement or Monitor statement;
- or trying to acquire (but not acquired yet) a readwrite lock;
Will the thread be interrupted in the above two situations when we call Interrupt?
2.
Is it ensured the Finally block for ThreadInterruptedException (for Thread.Interrupt called), and Finally block for ThreadAbortException (for Thread.Abort called) be ensured to be executed? If yes, I can rely on resource relase method there to ensure no resource leak.
regards,
George
|
|
|
|
|
1) A thread blocked while awaiting a lock has a ThreadState of WaitSleepJoin. A thread blocked in this state can be forcibly released by another thread calling its Interrupt or Abort method.
2) The finally block gets always executed.
SkyWalker
|
|
|
|
|