cb199911db_f.asp.htm

来自「C++builder学习资料C++builder」· HTM 代码 · 共 701 行 · 第 1/3 页

HTM
701
字号
<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;<b> void</b>  

<b>__fastcall</b> DisplayErrorMsg();&nbsp;&nbsp;&nbsp;<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> &nbsp; </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> &nbsp; </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> &nbsp; </p>  

  

<p class=Code><span class=Code><b>__fastcall</b>  

TQueryThread::TQueryThread(TForm *AOwner, </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;TStrings *SQLStrings, AnsiString  

DatabaseName, </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<b> int</b>  

intPriority): TThread(<b>true</b>)</span></p>  

  

<p class=Code><span class=Code>{</span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<b> char</b>  

*strSession; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;strSession = (<b>char</b> *) malloc(10); </span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<i> <span Class=CodeBlue>// Create Session. Use new session for each Thread. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;FSession = <b>new</b> TSession(NULL); </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;itoa(ThreadID, strSession, 10); </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<i> <span Class=CodeBlue>// Name Session with ThreadID, it's unique. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;FSession-&gt;SessionName=strSession; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<i> <span Class=CodeBlue>// Create Query. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;FQuery = <b>new</b> TQuery(NULL); </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;FQuery-&gt;SessionName =  

FSession-&gt;SessionName;&nbsp;&nbsp; <i  

style='mso-bidi-font-style:normal'><span Class=CodeBlue>// Attach session. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;FQuery-&gt;SQL-&gt;Assign(SQLStrings);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <i><span Class=CodeBlue>// Set query. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;FQuery-&gt;DatabaseName=DatabaseName;&nbsp;&nbsp;&nbsp; <i><span Class=CodeBlue>// Set Database. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;FDataSource = <b>new</b> TDataSource(NULL); <i><span Class=CodeBlue>// Create DataSource. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<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>&nbsp;&nbsp;FOwnerForm = AOwner; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<i> <span Class=CodeBlue>// Set Grids DataSource. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp; (<b>dynamic_cast</b>&lt;TfrmResults  

*&gt;(FOwnerForm))-&gt; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;dbgResults-&gt;DataSource=FDataSource; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;Priority = intPriority; </span></p>  

  

<p class=Code><span class=Code><i><span Class=CodeBlue>&nbsp;&nbsp;// Set thread  

to Free its resources when Terminated. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;FreeOnTerminate = <b>true</b>; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;FErrorMsg = &quot;&quot;; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;free(strSession); </span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;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> &nbsp; </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> &nbsp; </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>&nbsp;&nbsp;<b> if</b>  

((!Terminated) &amp;&amp; (FErrorMsg=="")) <i><span Class=CodeBlue>// Run thread. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;<b> try</b></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;{ </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Synchronize(DisconDataSource);&nbsp;&nbsp; <i><span Class=CodeBlue>// Disconnect DataSource. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FQuery-&gt;Active = <b>true</b>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> <span Class=CodeBlue>// Start Query. </span></i></span></p>  

  

<p class=Code><span class=Code><i><span Class=CodeBlue>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Connect  

Datasource, the grid will be filled.</span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Synchronize(ConnectDataSource); <i  

style='mso-bidi-font-style:normal'><span Class=CodeBlue></span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> <span Class=CodeBlue>// Pause so we can see the results of the query</span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> <span Class=CodeBlue>// before it's freed upon termination. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(10); </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;} </span></p>  

  

<p class=Code><span class=Code><i><span Class=CodeBlue>&nbsp;&nbsp;&nbsp;&nbsp;// Show an  

error message to the user on any exception. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;<b> catch</b>(...)  

</span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;{ </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FErrorMsg = &quot;Error executing  

query.&quot;; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Synchronize(DisplayErrorMsg); </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;} </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> &nbsp; </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> &nbsp; </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>&nbsp;&nbsp;// Close  

Query.</span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;FQuery-&gt;Active = <b>false</b>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> <span Class=CodeBlue></span></i></span></p>  

  

<p class=Code><span class=Code><i><span Class=CodeBlue>&nbsp;&nbsp;// Disconnect  

Datasource from Query.</span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;FDataSource-&gt;DataSet = NULL;&nbsp;&nbsp; <i><span Class=CodeBlue></span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<i> <span Class=CodeBlue>// Set label. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp; (<b>dynamic_cast</b>&lt;TfrmResults  

*&gt;(FOwnerForm))-&gt; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;lblDisplay-&gt;Caption=&quot;Starting  

Query&quot;; </span></p>  

  

<p class=Code><span class=Code>}</span></p>  

  

<p class=BodyText> &nbsp; </p>  

  

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?