Click here to Skip to main content
15,867,453 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi guys.
Recently I've encountered with problem of creation Process from dedicated thread.
Method which creates process look-like this
C#
public static string ExecuteDcmtk(string exe, string args, string workingDir)
        {
            string result;
            Process p = new Process();
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.FileName = exe;
            p.StartInfo.Arguments = args;
            p.StartInfo.WorkingDirectory = workingDir;
            p.Start();
            result = p.StandardOutput.ReadToEnd();
            p.WaitForExit();
            return result;
        }


In my thread i call this method and as a result caught next exception: System.Threading.ThreadAbortException
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
Who can help me with this issue?
thread propertie ISBackground is set to true.
Posted
Comments
Sergey Alexandrovich Kryukov 11-Jun-12 14:10pm    
Where is the call to Thread.Abort in your code? In what thread do you have this exception?
--SA
Oleksandr Kulchytskyi 11-Jun-12 15:46pm    
I do not use Thread.Abort. This can corrupt workflow state.
I use CancellationtokenSource and IsCancelled property for monitoring whether cancellation is requested,
thread run in infinite loop and periodically , say one time in 5 minute must run process.
Sergey Alexandrovich Kryukov 11-Jun-12 17:08pm    
It won't corrupt anything if you use if with full understanding of how it works. Nevertheless, I don't believe there is such thing as the miracle: if you have ThreadAbortException, it means that Thread.Abort was called with the thread where you have this exception. If you did not do it, some library code you use might do it.
--SA
Sergey Alexandrovich Kryukov 11-Jun-12 14:47pm    
As I understand, the only reason to have a dedicated thread for this is WaitForExit. But this wait is only needed when this thread notifies some other thread asynchronously about the event of the termination of the child process, otherwise it should simply return without wait; and a separate thread would not be needed. So, why do you wait in a separate thread without doing anything about it?
--SA

Please see my comments to the question. There must be a call to Thread.Abort somewhere. And your dedicate thread and the wait for the termination of the child process should have a reason, but this is not shown in your code.

Exceptions are not errors. (Important point many developers miss.) The exception System.Threading.ThreadAbortException is the very important exception used to process asynchronous Thread.Abort. It is used in the thread being aborted and allows this thread to exit correctly after abort, performing some post-mortal will of the thread, so it can finalize important object and perform other actions making abortion of the thread safe and correct. In many cases, this aspect of programming is not trivial.

Before explaining how it works, let me give you a word of warning. The method Thread.Abort is a very powerful method, and it is considered correct and safe, in contrast to deprecated Thread.Suspend because it is unsafe, and in contrast to Windows API TerminateThread, which is not even included in .NET API. Nevertheless, you should use this powerful method only if you perfectly understand how it works and what are the possible consequences. There is a class of application where the collaborative termination of the thread is impossible by the nature of the task, then this method is indispensable. If you are not 100% comfortable with this method, you should better use collaborative method: a thread simply exists its main method when the work is done. The other thread can instruct this thread to terminate by passing some request to is, which should be checked by the thread to be terminated periodically. Such cooperative termination is explained here:
http://msdn.microsoft.com/en-us/library/7a2f3ay4%28v=vs.90%29.aspx[^].

The method Thread.Abort uses exception seeding. Before .NET emerged, I saw an article from the Microsoft developer who demonstrated the technique on Windows API. Unfortunately, at this moment I don't have my literature references list to find out the original work. The code is platform-dependent, different for different Windows implementations for different instruction-set architectures, but it is based on documented Windows API. So, how to cause thread termination asynchronously to this thread? The thing is: the threads are scheduled by system scheduler; and their content is stored in the system memory. Windows API has documented access to this storage. So, a terminating thread can pause the thread to be terminated for a short time. The thread context is flashed to the system memory. Then the Instruction Pointer of suspended thread is modified to jump to some code. Of course, when the thread jumps instruction flow to some fixed code fragment, the thread's stack gets messed up. There is only one case when it does not matter. What case? When the fragment of code the thread jumps to never returns but throws exception instead. (To understand it, you should have good understanding on how exceptions work and what they do to the thread's stack.) And what is that exception? Right, this is that very ThreadAbortException. I actually implemented such mechanism, that's why I know the detail. This is how it all really works in .NET and other CLR implementations.

Now, being perfectly safe in principle, abortion of the thread is still unsafe in certain cases. One case is constructing some objects in the thread which can potentially be aborted. The behavior of the code aborted in the state when some objects are "half-constructed" is unpredictable. Everything has its work-around. You can simply avoid such unsafe operations in a thread which can be aborted, or you can protect it from abortion by avoiding direct abort. You can provide an indirect abort method (still to be called from a different thread) is a thread wrapper interlocked with the lock statement, with the possibility to deny or defer abortion in certain critical sections of the code.

[EDIT #1]

Important: In contrast to what would be expected based on common sense, the methods System.Threading.Thread.BeginCriticalRegion and System.Threading.Thread.EndCriticalRegion do not provide required protection from the cases I mentioned in the previous paragraph. According to the documentation, they only notify the host that "the effects of a thread abort or unhandled exception might jeopardize other tasks in the application domain". Please see:

http://msdn.microsoft.com/en-us/library/system.threading.thread.aspx[^] (see BeginCriticalRegion),
http://msdn.microsoft.com/en-us/library/system.threading.thread.begincriticalregion.aspx[^].

You can create a period where the thread spend extended period of time in the critical region and try to abort it from another thread. It will be aborted!

[END EDIT #1]

[EDIT #2]

I also noticed that you use Thread.IsBackground = true; and would like to warn about it. Indeed, the thread marked as a background thread will be terminated automatically after the main thread of the application is terminated; and this is the main difference between a background and non-background thread. It looks convenient and can work, but in most situations it's less predictable the with Thread.Abort. There is no a way to terminate a thread at deterministic time, but with cooperative termination or with Thread.Abort, your can control the order of some of the operations and guarantee that, say, one thread is ready for termination of some other thread. If you leave it uncontrolled relying on the automatic termination of a background thread, order of operations is unpredictable. It still can be used in very simple situation of the end of application lifetime and order of operations and other affected detail is not important. Again, you can only do it if you clearly understand how it works and affects your application termination.

[END EDIT #2]

[EDIT #3]

Please see also my past answer on related topic:
Close correcly the thread inside a dll[^].

[END EDIT #3]

I did not provide detail of the mechanisms of such advanced method of thread termination and safety measures because I'm not sure you need them. If interested, you are welcome to ask further questions.

—SA
 
Share this answer
 
v11
Comments
Oleksandr Kulchytskyi 11-Jun-12 15:48pm    
My 5 to your answer , As always, you are giving a very informative answers and advices. Codeproject must proud , that have such experienced people like you !
Sergey Alexandrovich Kryukov 11-Jun-12 17:05pm    
You are welcome, and thank you for your nice words.
If you like it so much, will you accept the answer formally (green button)?
By the way, it won't prevent you from accepting another one.
Thank you.
--SA
Maciej Los 11-Jun-12 17:49pm    
I have no words... only WOW!
BIG 5!
Sergey Alexandrovich Kryukov 11-Jun-12 18:00pm    
Thank you very much, Maciej.
By the way, I added important detail I learned in last year, another word of caution; after [EDIT].
--SA
Prasad_Kulkarni 12-Jun-12 0:28am    
Simply great! Hats off to your answer SA.
5 is really less for such informative answer..
I found and resolved issue. In my question i didnt notice, that this exception occurred in my TestMethod in Unit test project
The problem has been buried in Visual Studio Unit test settings.
Thread abort exception was thrown by Visual Studio, as i noticed in my thread is run in infinite loop and periodically one time in 10 - 20 sec run process. For waiting ability i use Thread.Sleep method. After some period of time, let's say , after 2 minutes, in debug mode when VS steps to Sleep method , it waits , and than process begin to hungs up and after that throws ThreadAbortException.
When i set in VS project setting visual studio hosting property to true,
my this issue didnt repeat.
But thanks you all for informative answers =)
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900