Threading in Delphi for .NET - Threading Exceptions
(Page 15 of 15 )
Exceptions need to be dealt with appropriately in order to avoid threads terminating prematurely. Any exception within a thread that is not handled will cause the thread to be terminated. Therefore, it is a good programming practice to at least report all exceptions and handle those exceptions that are expected.
System.Threading.ThreadAbortException
Calling the Thread.Abort() method will raise the ThreadAbortException on the target thread. Normally, this will cause the thread to terminate. However, a thread can catch the ThreadAbortException and choose to ignore it by using the Thread.ResetAbort() method.
There are two overloaded Abort() methods. One method does not take any parameters; the other takes a System.Object that provides state information to the thread. This parameter is examined by looking at the ExceptionState property of the ThreadAbortException. Listing 14.18 demonstrates how to handle the ThreadAbortException, taken from ThreadingExceptions.dpr.
Listing 14.18 ThreadingExceptions Example
1: program ThreadingExceptions;
2: {$APPTYPE CONSOLE}
3:
4: //
5: // This example demonstrates ThreadingExceptions.
6: // - ThreadAbortException is handled, and reset
7: // - ThreadInterruptedException is handled
8: // - ThreadStateException is handled
9: // - SynchronizationLockException is handled
10: //
11:
12: uses
13: System.Threading;
14:
15: type
16: D4DNThreadMe = class
17: public
18: procedure MyThreadMethod;
19: end;
20:
21: procedure D4DNThreadMe.MyThreadMethod;
22: var
23: numAborts : integer;
24:
25: begin
26: numAborts := 0;
27: while true do
28: begin
29: try
30: write('*');
31: Thread.Sleep(1000);
32: except
33: on e : System.Threading.ThreadInterruptedException do
34: begin
35: writeln('Handled ThreadInterruptedException');
36: end;
37: on e : System.Threading.ThreadAbortException do
38: begin
39: writeln('Handled threadAbortException');
40: inc(numAborts);
41: if numAborts = 1 then
42: Thread.ResetAbort;
43: end;
44: on e : exception do
45: begin
46: writeln('Unhandled exception ',e.message);
47: raise;
48: end;
49: end;
50: end;
51: end;
52:
53: var
54: thrdclass1 : D4DNThreadMe;
55: thrd1 : Thread;
56: cmd : string;
57: bDone : boolean;
58:
59: begin
60: System.Console.WriteLine('Staring threading exceptions example...');
61:
62: // create myDotNetThread instance
63: thrdclass1 := D4DNThreadMe.create;
64: thrd1 := Thread.Create(@thrdclass1.MyThreadMethod);
65: thrd1.Start;
66:
67: bDone := false;
68: while not bDone do
69: begin
70: System.Console.WriteLine('Enter A = Abort, I = Interrupt, ' +
71: 'S = ThreadStateException, L = SyncLockException');
72: cmd := System.Console.ReadLine.ToUpper;
73: if (cmd = 'A') then
74: thrd1.Abort // raise a ThreadAbortException
75: else if (cmd = 'I') then
76: thrd1.Interrupt // raise a ThreadInterruptedException
77: else if (cmd = 'S') then
78: begin
79: try
80: thrd1.Start
81: except
82: on e : System.Threading.ThreadStateException do
83: begin
84: System.Console.WriteLine('Handled ThreadStateException');
85: end;
86: end;
87: end
88: else if (cmd = 'L') then
89: begin
90: try
91: // needs to be wrapped in an Enter/Exit() block
92: System.Threading.Monitor.Wait(thrd1);
93: except
94: on e : System.Threading.SynchronizationLockException do
95: begin
96: System.Console.WriteLine('Handled SynchronizationLockException');
97: end;
98: end;
99: end
100: else
101: bDone := true;
102: end;
103:
104: // ensure that the thread is terminated
105: thrd1.Abort;
106: Thread.Sleep(1000);
107: thrd1.Abort;
108:
109: System.Console.WriteLine('Done - main');
110: end.
Note: Find the code on the CD: \Code\Chapter 14\Ex09\.
System.Threading.ThreadInterruptedException
Threads that are in a WaitSleepJoin state can be interrupted by using the Thread.Interrupt() method. If a thread is not in the WaitSleepJoin state, the exception will fire the next time that it goes into that state. Unhandled, this exception will terminate the thread. Listing 14.18 shows an example of the ThreadInterrupedException.
System.Threading.ThreadStateException
Suppose that an application has two threads—A and B. If thread A tries to coerce thread B into an invalid state, a ThreadStateException will be raised in thread A. Trying to transition from a running state to a restarted state or from a terminated state to a restarted state are both illegal state transitions that will trigger the ThreadStateException. Listing 14.18 contains an example of how the ThreadStateException is raised and handled.
System.Threading.SynchronizationLockException
Attempting to use certain methods of the Monitor class incorrectly will raise the SynchronizationLockException. For example, calling the Wait() method outside of a pair of Enter()/Exit() methods triggers this exception. Listing 14.18 illustrates an example.
Garbage Collection and Threading
Garbage collection can occur at any time. In order to perform its job, all threads are suspended. If any managed threads are currently executing unmanaged code, these threads are resumed. However, before resuming these threads, the CLR inserts code to suspend the thread when it returns to managed code. These threads are allowed to resume because memory is pinned (locked down) when it is referenced by unmanaged code.
This chapter is from Delphi for .NET Developer's Guide, by Xavier Pacheco (Sams, 2004, ISBN: 0-672-32443-1). Check it out at your favorite bookstore today.
Buy this book now. |
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |