cb199911db_f.asp.htm

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

HTM
701
字号
<p class=BodyText> Now that  

we've disconnected the DataSource, we can execute the query. To execute the  

query, we set <i>TQuery</i>'s <i>Active</i>  

property to <b>true</b>. It's important to note that we don't open the query in  

a S<i>ynchronized</i> method. This allows other threads to continue executing  

while our query is running. If we were to open our query in a <i>Synchronized</i>  

method, the application would operate in the same manner as a single-threaded  

application. </p>  

  

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

  

<p class=BodyText> After  

the query is open, we need to reconnect <i>TDataSource</i>  

to display our results to the user. To do this, we call another procedure using  

<i>Synchronize</i>. Because we're making  

changes to the screen, we must ensure this thread is the only one associated  

with the program that's executing. When the connection is made, <i  

style='mso-bidi-font-style:normal'>TDataSource</i> will cause <i  

style='mso-bidi-font-style:normal'>TDBGrid</i> on the form to re-draw and  

display the query results. The code to connect the DataSource is shown in  

Figure 6. </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::ConnectDataSource()</span></p>  

  

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

  

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

*strRecords; </span></p>  

  

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

*strDone; </span></p>  

  

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

intCounter; </span></p>  

  

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

  

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

  

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

  

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

  

<p class=Code><span class=Code>&nbsp;&nbsp;FDataSource-&gt;DataSet=FQuery; </span></p>  

  

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

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

  

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

  

<p class=Code><span class=Code>&nbsp;&nbsp;<i> <span Class=CodeBlue>// Keep number of records processed updated, and change </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<i> <span Class=CodeBlue>// the label on the main form to reflect this. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;frmMain-&gt;intProcessedRecords =</span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;frmMain-&gt;intProcessedRecords +  

FQuery-&gt;RecordCount; </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;itoa(frmMain-&gt;intProcessedRecords,  

strRecords, 10); </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;frmMain-&gt;lblProcessed-&gt;Caption=strRecords; </span></p>  

  

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

  

<p class=Code><span class=Code>&nbsp;&nbsp;<i> <span Class=CodeBlue>// Now that the query has executed successfully, update </span></i></span></p>  

  

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

on the main form. </span></i></span></p>  

  

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

(atoi(frmMain-&gt;lblCompleted-&gt;Caption.c_str()) + 1); </span></p>  

  

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

  

<p class=Code><span class=Code>&nbsp;&nbsp;frmMain-&gt;lblCompleted-&gt;Caption =  

strDone; </span></p>  

  

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

  

<p class=Code><span class=Code>&nbsp;&nbsp;<i> <span Class=CodeBlue>// Free our allocated space. </span></i></span></p>  

  

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

  

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

  

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

  

<p class=Captions><b>Figure  

6:</b> Code for  

connecting the DataSource. </p>  

  

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

  

<p class=BodyText> Lastly,  

we use the <i>Sleep</i> function to make the thread pause for 10 seconds, so  

the result set is displayed in the <i>TDBGrid</i>  

long enough for the user to see it. After that, the thread object is completed.  

Once the <i>Execute</i> method has finished running in a thread, it's  

considered terminated and the <i>Destructor</i> method will be fired. At this  

point, the resources are freed and the query will no longer display the results. </p>  

  

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

  

<p class=BodyText> As  

mentioned previously, problems can occur if threads are misused in an  

application. In the next few simple examples, we'll demonstrate some of the  

more common problems and how they can be resolved. </p>  

  

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

  

<p class=Subheads>Thread  

Starvation</p>  

  

<p class=BodyText> Aside  

from syntax problems, the most common error that occurs in a multithreaded  

application is thread starvation. This is caused when an application has  

threads that are CPU intensive and set as high priority. In this situation,  

threads with a lower priority don't get enough processing resources (due to  

preemptive multitasking) and will never execute, i.e. they're "starved" of  

resources. </p>  

  

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

  

<p class=BodyText> Consider  

the example mentioned earlier where a multithreaded application is in use by a  

company that sells computer software to businesses. The program is able to  

input any information that comes from phone orders, and it's also able to  

generate invoices for the software that were sold for any period of time.  

Because the number of orders that haven't been invoiced could become quite  

large, the invoice calculation is a lengthy process. If a phone order comes in  

while the invoices are being calculated, the application is able to still  

handle the incoming call because it's a multithreaded application. We could  

create a thread starvation problem by setting the thread priority for the  

invoices to be higher than that of the phone order information entry. Because  

the invoices are being calculated at a high rate and the process is quite  

lengthy, Windows won't relinquish control of the processor to the thread that allows  

data entry. The result would be that a (now angry) customer wouldn't be able to  

place an order with the company. </p>  

  

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

  

<p class=BodyText> To solve  

this problem, we must first recognize that entering order data is the most  

important function that could occur, and as such, must be allowed to take  

precedence in the application. The solution is to set the thread priority of  

the invoice calculation to be less that that of the data entry thread. In our  

example application, we're able to change the thread priorities and witness the  

different effects. By setting our additional thread priority to be less than  

that of the main application, the priority of the main thread is given the  

processor time it requires for data entry. </p>  

  

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

  

<p class=Subheads>Thread  

Deadlock</p>  

  

<p class=BodyText> The  

second most common thread problem is known as thread deadlock. This occurs when  

a high-priority thread is waiting for the results of a thread with a lower  

priority. If the higher priority thread is not suspended first, it will preempt  

the lower priority thread, preventing it from being scheduled for processing.  

By doing this, the lower priority thread never gets any CPU time, and the  

higher priority thread never gets the result set that it needs. </p>  

  

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

  

<p class=BodyText> Thread  

deadlock can be solved by using the <i>WaitFor</i>  

method of a thread. This method waits until a particular thread has completed  

before continuing. We would simply wait for the lower-priority thread to  

complete before launching the higher-priority thread. Deadlock can also be  

solved if the higher-priority thread is suspended until the lower-priority thread  

has completed its processing. So, in an application, we create our  

high-priority thread with <i>CreateSuspended</i>  

set to <b>true</b>, and we would resume processing of the thread once the  

lower-priority thread completed, perhaps in the <i>OnTerminate</i> event of the low-priority thread. </p>  

  

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

  

<p class=BodyText> It's  

important to understand how threads operate to successfully create  

multithreaded applications. Often, these kinds of thread problems will occur  

only under certain circumstances and can make debugging a headache for any  

developer. Knowing what to look for and expect out of threaded applications can  

prevent many future problems for users. </p>  

  

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

  

<p class=Subheads>Conclusion</p>  

  

<p class=BodyText> Multithreaded  

programming can be a very powerful development technique when used properly.  

Database programming is one of the best and most widely discussed uses for this  

type of development. This article has explored a few techniques that can be  

used in the creation of these types of applications. Though not a trivial task,  

in certain cases adding multithreaded queries to an application can make for a  

much more powerful and productive system. C++Builder includes all the tools you  

need to provide these capabilities to your users. </p>  

  

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

  

<p class=BodyText> <i>The project<b> </b>referenced in this article is<b  

style='mso-bidi-font-weight:normal'> </b>available for <a href="download/cb199911db_f.zip" tppabs="http://www.cbuilderzine.com/features/1999/11/cb199911db_f/cb199911db_d.asp">download</a>.</i></p> 

 

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

 

 

 

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

 

 

 

</td> 

</TR> 

</TABLE> 

 

 

</BODY> 

</HTML> 

⌨️ 快捷键说明

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