📄 cb199910db_f.asp.htm
字号:
is only available at run time. In addition to the <I
style="mso-bidi-font-style: normal">Handle</I> property, the <I
style="mso-bidi-font-style: normal">ThreadId</I> property may be required
in some Win32 API calls. Note that the <I>ThreadId</I> property is also a
read-only and run-time property of the object. These properties are
read-only because Windows determines their values when the thread objects
are created. </P>
<P class=BodyText> </P>
<P class=BodyText>A critical property in the <I>TThread</I> class is the
<I>Priority</I> property. This property allows the programmer to define
how much CPU time a particular thread is given. The default setting for
<I>Priority</I> is <I>tpNormal</I>, meaning the thread is given normal CPU
priority compared to the thread priority of the application from which
it's called. There are seven levels of thread priority, ranging from
<I>tpIdle</I> to <I
style="mso-bidi-font-style: normal">tpTimeCritical</I>. A setting of
<I>tpIdle</I> means the thread will run only if the CPU is idle, and no
other threads are scheduled to be processed. <I>tpTimeCritical</I> gives
the thread near-complete control of the processor until the thread is
completed. The remaining levels of thread priority give the thread more or
less priority than that of the application from which it's called. </P>
<P class=BodyText> </P>
<P class=BodyText>It's important to make sure that appropriate priorities
are set between different threads, or certain threads may become "starved"
of CPU time and never finish processing. Typically, we want to set the
priority of user-interface threads to be higher than background threads
that the user doesn't interact with, so the program is responsive to the
user. However, processes will still be going on behind the scenes. </P>
<P class=BodyText> </P>
<P class=BodyText>The <I style="mso-bidi-font-style: normal">Suspended</I>
property of the thread tells whether the particular thread has been halted
using the <I>Suspend</I> method. (This method will be described in more
detail in the next section.) </P>
<P class=BodyText> </P>
<P class=BodyText>The <I
style="mso-bidi-font-style: normal">Terminated</I> property of the thread
checks to see if thread processing is completed. This can be done manually
by calling <I style="mso-bidi-font-style: normal">Terminate</I>. However,
it will occur automatically when the natural execution path of the thread
is completed. (The <I style="mso-bidi-font-style: normal">Terminate</I>
method call will also be described in more detail in the next section.)
</P>
<P class=BodyText> </P>
<P class=BodyText>Some of the properties of the thread will determine how
the thread is going to behave when it's executed. If the user wants to
free the thread as soon as it's done processing, the
<I>FreeOnTerminate</I> property can be set to <B>true</B>, eliminating the
need to free the <I>Thread</I> object. If for some reason the programmer
wants to maintain control of freeing the <I>Thread</I> object,
<I>FreeOnTerminate</I> can be set to <B>false</B>, and the object can be
freed manually. </P>
<P class=BodyText> </P>
<P class=BodyText>If the user wishes to return any data about the thread,
this can be stored in the <I
style="mso-bidi-font-style: normal">ReturnValue</I> property of the
thread. This applies later to the <I>WaitFor</I> method, which waits for
the termination of the thread and gets the <I>ReturnValue</I>.</P>
<P class=BodyText> </P>
<P class=Subheads>Methods</P>
<P class=BodyText>The first <I>TThread</I> class method that must be used
is, obviously, the <I>Constructor</I> method. When creating a thread, the
programmer must specify whether the thread should execute immediately,
once it's created. This is done by using the Boolean parameter
<I>CreateSuspended</I>, which is passed in the <I>Constructor</I> method.
If set to <B>false</B>, the thread begins processing immediately. If set
to <B>true</B>, the thread begins processing when the <I>Resume</I> method
is called. </P>
<P class=BodyText> </P>
<P class=BodyText>The <I style="mso-bidi-font-style: normal">Resume</I>
and <I>Suspend</I> methods are used to pause and restart threads. As
mentioned previously, a new thread with <I>CreateSuspended</I> set to
<B>true</B> must get a call to <I>Resume</I> before processing will occur.
</P>
<P class=BodyText> </P>
<P class=BodyText>The <I>DoTerminate</I> method simply fires the
<I>OnTerminate</I> event of the <I>TThread</I> class, if there is any code
attached to the event. </P>
<P class=BodyText> </P>
<P class=BodyText>The <I style="mso-bidi-font-style: normal">Terminate</I>
method sets the <I style="mso-bidi-font-style: normal">Terminated</I>
property to <B>true</B>. The code put into the <I>Execute</I> method needs
to check to see if the <I>Terminated</I> property is set to <B>true</B> to
determine when to stop processing a thread. If no facilities are coded to
check this property, <I>Terminate</I> won't stop the thread from running.
</P>
<P class=BodyText> </P>
<P class=BodyText>The <I style="mso-bidi-font-style: normal">WaitFor</I>
method waits for the termination of the query, and returns the value
stored in <I>ReturnValue</I>.</P>
<P class=BodyText> </P>
<P class=BodyText>The <I
style="mso-bidi-font-style: normal">Synchronize</I> method is very
important for creating stable multithreaded environments. It's required
whenever a method must be called that references any components, forms, or
other resources that may be shared. The reason for this is because failure
to do so can cause multithread conflicts with the main thread of the
application, otherwise known as memory locking. <I>Synchronize</I>
suspends the execution of the current thread, and uses the main
application thread to perform the action specified in the method that was
passed to it. </P>
<P class=BodyText> </P>
<P class=BodyText>As an example of how failure to use <I>Synchronize</I>
could cause problems, suppose that two threads try to access an edit box
at the same time to change the value of its text. A conflict would occur
when the two threads were trying to access the edit box at the same time.
Calling the method that changes the edit box text through the
<I>Synchronize</I> method of the thread would be a solution to this. The
<I>Synchronize</I> method call looks like the following: </P>
<P class=BodyText> </P>
<P class=Code><SPAN class=Code><B>void</B> <B
style="mso-bidi-font-weight: normal">__fastcall</B>
Synchronize(TThreadMethod <I>Method</I>);</SPAN></P>
<P class=BodyText> </P>
<P class=BodyText>The method to be executed is passed as the
<I>TThreadMethod</I> of the <I>Synchronize</I> method. </P>
<P class=BodyText> </P>
<P class=BodyText>The <I style="mso-bidi-font-style: normal">Execute</I>
method is another important part of a <I>TThread</I> class. This method is
fired immediately after the thread object is created. It should contain
the code necessary to perform the task for which the thread was created.
The <I>Execute</I> method must be overridden with each new thread, so the
appropriate code can be attached to it. These properties and methods will
be described in more detail later as they are used in the sample programs
included in this article. </P>
<P class=BodyText> </P>
<P class=BodyText>Because we need to override certain methods of the
<I>TThread</I> class before it's used, we'll never create and use the
<I>TThread</I> class directly. The reason for this is simple; because we
haven't written code to tell the thread what to do in the <I>TThread</I>
class, we need to descend from <I>TThread</I>, and then customize our new
class. </P>
<P class=BodyText> </P>
<P class=Subheads>Using Threads in Applications</P>
<P class=BodyText>Now that we've reviewed the concepts and terminology of
the <I>TThread</I> class, let's put them to use. For our first example of
multithreading, a simple shape-changing application will be used. Each of
the three shapes displayed on the screen are changed to different shapes
by three separate threads. The application continually changes the shapes
on the main screen of the form based on the priority of the threads for
each, which are adjusted by using the track bar. When executed, the form
for the application resembles Figure 1. </P>
<P class=BodyText> </P><IMG align=left height=144
src="images/cb199910db_f_image002.jpg" width=333
tppabs="http://www.cbuilderzine.com/features/1999/10/cb199910db_f/cb199910db_f_image002.jpg">
<BR clear=all style="mso-ignore: vglayout"><B>Figure 1:</B> The example
shape-changing application.
<P class=BodyText> </P><BR clear=all>
<P class=BodyText>The form creates three new threads for each of the three
shapes. The threads are called with the value of <B>true</B> in
<I>CreateSuspended</I>, so the threads are not active and the shapes are
not changing on startup. When the Start button is clicked, all of the
threads are resumed and the shapes will change rapidly. The position of
the pointer on each of the track bars represents the thread priority given
to each of the three shape threads. To change the thread priority, simply
slide the track bar. Clicking the Stop button will suspend all of the
threads. Closing the form terminates the threads and frees them from
memory. </P>
<P class=BodyText> </P>
<P class=BodyText>As mentioned previously, a custom thread class must be
created in order to override the <I>Execute</I> method of the thread and
make it perform a custom action, in this case the action to change the
shape of the objects. The <I
style="mso-bidi-font-style: normal">TShapeThread</I> class was created to
accomplish this task. The object class declaration for the
<I>TShapeThread</I> object is shown in Figure 2. </P>
<P class=BodyText> </P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>//
-----------------------------------------------------</SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#ifndef
sthreadH</SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#define
sthreadH</SPAN></SPAN></P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>//
-----------------------------------------------------</SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include
<vcl\sysutils.hpp> </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include
<vcl\controls.hpp> </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include
<vcl\classes.hpp> </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include
<vcl\forms.hpp> </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -