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> </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> </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> <b> char</b>
*strRecords; </span></p>
<p class=Code><span class=Code> <b> char</b>
*strDone; </span></p>
<p class=Code><span class=Code> <b> int</b>
intCounter; </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> strRecords = (<b>char</b> *) malloc(10); </span></p>
<p class=Code><span class=Code> strDone = (<b>char</b> *) malloc(10); </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> FDataSource->DataSet=FQuery; </span></p>
<p class=Code><span class=Code> </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="Query
Done"; </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> <i> <span Class=CodeBlue>// Keep number of records processed updated, and change </span></i></span></p>
<p class=Code><span class=Code> <i> <span Class=CodeBlue>// the label on the main form to reflect this. </span></i></span></p>
<p class=Code><span class=Code> frmMain->intProcessedRecords =</span></p>
<p class=Code><span class=Code> frmMain->intProcessedRecords +
FQuery->RecordCount; </span></p>
<p class=Code><span class=Code> itoa(frmMain->intProcessedRecords,
strRecords, 10); </span></p>
<p class=Code><span class=Code> frmMain->lblProcessed->Caption=strRecords; </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> <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> // the label
on the main form. </span></i></span></p>
<p class=Code><span class=Code> intCounter =
(atoi(frmMain->lblCompleted->Caption.c_str()) + 1); </span></p>
<p class=Code><span class=Code> itoa(intCounter, strDone, 10); </span></p>
<p class=Code><span class=Code> frmMain->lblCompleted->Caption =
strDone; </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> <i> <span Class=CodeBlue>// Free our allocated space. </span></i></span></p>
<p class=Code><span class=Code> free(strRecords); </span></p>
<p class=Code><span class=Code> 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> </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> </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> </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> </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> </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> </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> </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> </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> </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> </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> </p>
<p class=BodyText> </p>
</td>
</TR>
</TABLE>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?