cb199911db_f.asp.htm
来自「C++builder学习资料C++builder」· HTM 代码 · 共 701 行 · 第 1/3 页
HTM
701 行
<p class=Code><span class=Code> <b> void</b>
<b>__fastcall</b> DisplayErrorMsg(); <i> <span Class=CodeBlue>// Display any query error. </span></i></span></p>
<p class=Code><span class=Code>};</span></p>
<p class=Captions><b>Figure
3:</b> The class
declaration for <i>TQueryThread</i>.</p>
<p class=BodyText> </p>
<p class=BodyText> As
parameters to the method, we have: a reference to the form that created the
thread; the strings from the <i>TMemo</i> on
the main form, which is the query to be executed; the BDE alias, which the user
selected from the <i>TComboBox</i> from the
main form; and the priority that we're going to give our new thread. This
method does several important things. First it creates a new <i
style='mso-bidi-font-style:normal'>TSession</i> and <i>TDatabase</i> for itself. Each thread has its own <i>ThreadId</i>, which is
an integer. As mentioned earlier, the <i>ThreadId</i>
of a thread is used when making thread API calls. A consequence of this is that
no two <i>ThreadId</i> values will be the
same in the operating system. Because each session needs to be named uniquely,
we use the <i>ThreadId</i> as our <i
style='mso-bidi-font-style:normal'>SessionName</i>. We also need to create the <i
style='mso-bidi-font-style:normal'>TQuery</i> to execute the SQL statement. The
<i>TQuery</i> is then attached to the newly
created <i>TSession</i> and assigned the SQL
strings and the alias the user has specified. We also need to save a reference
to the form that created the thread so we can access components on the form
later. The <i>TDBGrid</i>, which is located on the form, is
then pointed to the new <i>TDataSource</i>. </p>
<p class=BodyText> </p>
<p class=BodyText> Next,
set the thread's <i>FreeOnTerminate</i>
property to <b>true</b>. This will cause the thread to automatically free its
resource when it's terminated. The <i>Resume</i>
method is called at the end of the <i>Create</i> method, because our thread was
created with <i>CreateSuspended</i> set to <b>true</b>.
This is important because, if the user sets <i>CreateSuspended</i>
to <b>false</b>, all the code in the <i>Constructor</i> method may not be
completed before the code in <i>Execute</i>
is called. The safe way to make sure the <i>Constructor</i> is done is to
create your thread with <i>CreateSuspended</i>
and call <i>Resume</i> at the end of the <i>Constructor</i>.
The <i>Constructor</i> for our thread is shown in Figure 4. </p>
<p class=BodyText> </p>
<p class=Code><span class=Code><b>__fastcall</b>
TQueryThread::TQueryThread(TForm *AOwner, </span></p>
<p class=Code><span class=Code> TStrings *SQLStrings, AnsiString
DatabaseName, </span></p>
<p class=Code><span class=Code> <b> int</b>
intPriority): TThread(<b>true</b>)</span></p>
<p class=Code><span class=Code>{</span></p>
<p class=Code><span class=Code> <b> char</b>
*strSession; </span></p>
<p class=Code><span class=Code> strSession = (<b>char</b> *) malloc(10); </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> <i> <span Class=CodeBlue>// Create Session. Use new session for each Thread. </span></i></span></p>
<p class=Code><span class=Code> FSession = <b>new</b> TSession(NULL); </span></p>
<p class=Code><span class=Code> itoa(ThreadID, strSession, 10); </span></p>
<p class=Code><span class=Code> <i> <span Class=CodeBlue>// Name Session with ThreadID, it's unique. </span></i></span></p>
<p class=Code><span class=Code> FSession->SessionName=strSession; </span></p>
<p class=Code><span class=Code> <i> <span Class=CodeBlue>// Create Query. </span></i></span></p>
<p class=Code><span class=Code> FQuery = <b>new</b> TQuery(NULL); </span></p>
<p class=Code><span class=Code> FQuery->SessionName =
FSession->SessionName; <i
style='mso-bidi-font-style:normal'><span Class=CodeBlue>// Attach session. </span></i></span></p>
<p class=Code><span class=Code> FQuery->SQL->Assign(SQLStrings); <i><span Class=CodeBlue>// Set query. </span></i></span></p>
<p class=Code><span class=Code> FQuery->DatabaseName=DatabaseName; <i><span Class=CodeBlue>// Set Database. </span></i></span></p>
<p class=Code><span class=Code> FDataSource = <b>new</b> TDataSource(NULL); <i><span Class=CodeBlue>// Create DataSource. </span></i></span></p>
<p class=Code><span class=Code> <i> <span Class=CodeBlue>// Save reference to the form the thread will display data
on. </span></i></span></p>
<p class=Code><span class=Code> FOwnerForm = AOwner; </span></p>
<p class=Code><span class=Code> <i> <span Class=CodeBlue>// Set Grids DataSource. </span></i></span></p>
<p class=Code><span class=Code> (<b>dynamic_cast</b><TfrmResults
*>(FOwnerForm))-> </span></p>
<p class=Code><span class=Code> dbgResults->DataSource=FDataSource; </span></p>
<p class=Code><span class=Code> Priority = intPriority; </span></p>
<p class=Code><span class=Code><i><span Class=CodeBlue> // Set thread
to Free its resources when Terminated. </span></i></span></p>
<p class=Code><span class=Code> FreeOnTerminate = <b>true</b>; </span></p>
<p class=Code><span class=Code> FErrorMsg = ""; </span></p>
<p class=Code><span class=Code> free(strSession); </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> Resume();</span></p>
<p class=Code><span class=Code>}</span></p>
<p class=Captions><b>Figure
4: </b>The <i>Constructor</i>
for our thread. </p>
<p class=BodyText> </p>
<p class=BodyText> Now that
we have set up the thread with all of the necessary components to run our
query, we need to code the action of executing and displaying the query
results. To do this, we override the <i>Execute</i>
method. Note that when you create a new <i>TThread</i>
object from C++Builder, it automatically overrides the <i>Execute</i> method
for you, so all that is necessary is to add the appropriate code. The <i
style='mso-bidi-font-style:normal'>Execute</i> method is automatically called
after the thread is created. This applies to all threads. The code for the <i
style='mso-bidi-font-style:normal'>Execute</i> method is shown in Figure 5. </p>
<p class=BodyText> </p>
<p class=Code><span class=Code><b>void</b> <b
style='mso-bidi-font-weight:normal'>__fastcall</b> TQueryThread::Execute()</span></p>
<p class=Code><span class=Code>{</span></p>
<p class=Code><span class=Code> <b> if</b>
((!Terminated) && (FErrorMsg=="")) <i><span Class=CodeBlue>// Run thread. </span></i></span></p>
<p class=Code><span class=Code> <b> try</b></span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> Synchronize(DisconDataSource); <i><span Class=CodeBlue>// Disconnect DataSource. </span></i></span></p>
<p class=Code><span class=Code> FQuery->Active = <b>true</b>; <i> <span Class=CodeBlue>// Start Query. </span></i></span></p>
<p class=Code><span class=Code><i><span Class=CodeBlue> // Connect
Datasource, the grid will be filled.</span></i></span></p>
<p class=Code><span class=Code> Synchronize(ConnectDataSource); <i
style='mso-bidi-font-style:normal'><span Class=CodeBlue></span></i></span></p>
<p class=Code><span class=Code> <i> <span Class=CodeBlue>// Pause so we can see the results of the query</span></i></span></p>
<p class=Code><span class=Code> <i> <span Class=CodeBlue>// before it's freed upon termination. </span></i></span></p>
<p class=Code><span class=Code> sleep(10); </span></p>
<p class=Code><span class=Code> } </span></p>
<p class=Code><span class=Code><i><span Class=CodeBlue> // Show an
error message to the user on any exception. </span></i></span></p>
<p class=Code><span class=Code> <b> catch</b>(...)
</span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> FErrorMsg = "Error executing
query."; </span></p>
<p class=Code><span class=Code> Synchronize(DisplayErrorMsg); </span></p>
<p class=Code><span class=Code> } </span></p>
<p class=Code><span class=Code>}</span></p>
<p class=Captions><b>Figure
5:</b> The <i>Execute</i>
method. </p>
<p class=BodyText> </p>
<p class=BodyText> First we
need to make sure the query is closed and disconnected from the <i
style='mso-bidi-font-style:normal'>TDataSource</i>. We do this by setting the <i
style='mso-bidi-font-style:normal'>TQuery</i>'s <i>Active</i> property to <b>false</b>,
and the <i>TDataSource</i>'s <i>DataSet</i> property to NULL.
It must be done in a synchronized function, because if any visual component is
connected to <i>TDataSource</i>, they will
be redrawn to show no data when the DataSet is disconnected from the
DataSource. Here is the method used to disconnect the query: </p>
<p class=BodyText> </p>
<p class=Code><span class=Code><b>void</b> <b
style='mso-bidi-font-weight:normal'>__fastcall</b>
TQueryThread::DisconDataSource()</span></p>
<p class=Code><span class=Code>{</span></p>
<p class=Code><span class=Code><i><span Class=CodeBlue> // Close
Query.</span></i></span></p>
<p class=Code><span class=Code> FQuery->Active = <b>false</b>; <i> <span Class=CodeBlue></span></i></span></p>
<p class=Code><span class=Code><i><span Class=CodeBlue> // Disconnect
Datasource from Query.</span></i></span></p>
<p class=Code><span class=Code> FDataSource->DataSet = NULL; <i><span Class=CodeBlue></span></i></span></p>
<p class=Code><span class=Code> <i> <span Class=CodeBlue>// Set label. </span></i></span></p>
<p class=Code><span class=Code> (<b>dynamic_cast</b><TfrmResults
*>(FOwnerForm))-> </span></p>
<p class=Code><span class=Code> lblDisplay->Caption="Starting
Query"; </span></p>
<p class=Code><span class=Code>}</span></p>
<p class=BodyText> </p>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?