📄 ch18.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
<SCRIPT LANGUAGE="JavaScript">
<!--
function popUp(pPage) {
var fullURL = document.location;
var textURL = fullURL.toString();
var URLlen = textURL.length;
var lenMinusPage = textURL.lastIndexOf("/");
lenMinusPage += 1;
var fullPath = textURL.substring(0,lenMinusPage);
popUpWin = window.open('','popWin','resizable=yes,scrollbars=no,width=525,height=394');
figDoc= popUpWin.document;
zhtm= '<HTML><HEAD><TITLE>' + pPage + '</TITLE>';
zhtm += '</head>';
zhtm += '<BODY bgcolor="#FFFFFF">';
zhtm += '<IMG SRC="' + fullPath + pPage + '">';
zhtm += '<P><B>' + pPage + '</B>';
zhtm += '</BODY></HTML>';
window.popUpWin.document.write(zhtm);
window.popUpWin.document.close();
// Johnny Jackson 4/28/98
}
//-->
</SCRIPT>
<!--<link rel="stylesheet" href="../../../../includes/stylesheets/ebooks.css">-->
<META NAME="GENERATOR" Content="Symantec Visual Page Mac 1.1.1">
<TITLE>Teach Yourself Visual C++ 6 in 21 Days -- Ch 18 -- Doing Multiple Tasks at One Time--Multitasking</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF">
<H1 ALIGN="CENTER"><IMG SRC="../button/sams.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM"
BORDER="0"><BR>
Teach Yourself Visual C++ 6 in 21 Days</H1>
<CENTER>
<P><A HREF="../ch17/ch17.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ch19/ch19.htm"><IMG
SRC="../button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"
BORDER="0"></A><A HREF="../index.htm"><IMG SRC="../button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A>
<HR>
</CENTER>
<H1 ALIGN="CENTER">- 18 -<BR>
Doing Multiple Tasks at One Time--Multitasking</H1>
<H1></H1>
<UL>
<LI><A HREF="#Heading1">What Is Multitasking?</A>
<UL>
<LI><A HREF="#Heading2">Performing Multiple Tasks at One Time</A>
<LI><A HREF="#Heading3">Idle Processing Threads</A>
<LI><A HREF="#Heading4">Spawning Independent Threads</A>
</UL>
<LI><A HREF="#Heading5">Building a Multitasking Application</A>
<UL>
<LI><A HREF="#Heading6">Creating a Framework</A>
<LI><A HREF="#Heading7">Designing Spinners</A>
</UL>
<LI><A HREF="#Heading8">Supporting the Spinners</A>
<UL>
<LI><A HREF="#Heading9">Adding the OnIdle Tasks</A>
<LI><A HREF="#Heading10">Adding Independent Threads</A>
</UL>
<LI><A HREF="#Heading11">Summary</A>
<LI><A HREF="#Heading12">Q&A</A>
<LI><A HREF="#Heading13">Workshop</A>
<UL>
<LI><A HREF="#Heading14">Quiz</A>
<LI><A HREF="#Heading15">Exercises</A>
</UL>
</UL>
<P>
<HR SIZE="4">
<BR>
Sometimes it is convenient to let your applications do more than one thing at a time.
Your application could write a backup file or print in the background while the user
is working on the same document. Your application could perform calculations while
the user enters new data or draws multiple images simultaneously. There are many
different reasons why you might want to add this capability, called multitasking,
to your applications. Windows provides several facilities specifically for building
this into applications.</P>
<P>Today, you will learn</P>
<P>
<UL>
<LI>How tasks can be performed while an application is idle.
<P>
<LI>How tasks can run independently of the rest of the application.
<P>
<LI>How to coordinate access to resources that are shared between multiple independent
tasks.
<P>
<LI>How to start and stop independently running tasks.
</UL>
<H2><A NAME="Heading1"></A>What Is Multitasking?</H2>
<P>In the days of Windows 3.<I>x</I>, all Windows applications were single-threaded,
with only one path of execution at any point in time. The version of multitasking
that Windows 3.<I>x</I> offered is known as cooperative multitasking. The key to
cooperative multitasking is that each individual application makes the decision about
when to give up the processor for another application to perform any processing that
it might be waiting to perform. As a result, Windows 3.<I>x</I> was susceptible to
an ill-behaved application that would hold other applications prisoner while it performed
some long, winding process or even got itself stuck in some sort of loop.</P>
<P>With Windows NT and Windows 95, the nature of the operating system changed. No
more cooperative multitasking--the new method was preemptive multitasking. With preemptive
multitasking, the operating system decides when to take the processor away from the
current application and give the processor to another application that is waiting
for it. It doesn't matter whether the application that has the processor is ready
to give it up; the operating system takes the processor without the application's
permission. This is how the operating system enables multiple applications to perform
computation-intensive tasks and still let all the applications make the same amount
of progress in each of their tasks. Giving this capability to the operating system
prevents a single application from holding other applications prisoner while hogging
the processor.</P>
<BLOCKQUOTE>
<P>
<HR>
<STRONG>NOTE:</STRONG> With the 16/32 bit structure of Windows 95, it is still possible
for an ill-behaved 16-bit application to lock up the system because a large amount
of 16-bit code remains a core part of the operating system. The 16-bit code on Windows
95 is still a cooperative multitasking environment, so only one application can execute
16-bit code at a time. Because all the USER functions, and a good portion of the
GDI functions, thunk down to the 16-bit version, it is still possible for a single
16-bit application to lock up the entire system.<BR>
On Windows NT, if all of the 16-bit applications run in a shared memory space, an
ill-behaved application can lock up all of the 16-bit applications, but this has
no effect on any 32-bit applications.
<HR>
</BLOCKQUOTE>
<H3><A NAME="Heading2"></A>Performing Multiple Tasks at One Time</H3>
<P>Along with the capability to allow multiple applications to run simultaneously
comes the capability for a single application to execute multiple threads of execution
at any time. A thread is to an application what an application is to the operating
system. If an application has multiple threads running, it is basically running multiple
applications within the whole application. This lets the application accomplish more
things simultaneously, such as when Microsoft Word checks your spelling at the same
time you are typing your document.</P>
<P>
<H3><A NAME="Heading3"></A>Idle Processing Threads</H3>
<P>One of the easiest ways to let your application perform multiple tasks at one
time is to add some idle processing tasks. An idle processing task is a task that
is performed when an application is sitting idle. Literally, a function in the application
class is called when there are no messages in the application message queue. The
idea behind this function is that while the application is idle, it can perform work
such as cleaning up memory (also known as garbage collection) or writing to a print
spool.</P>
<P>The OnIdle function is a holdover from the Windows 3.<I>x</I> days. It is a member
of the CWinApp class, from which your application class is inherited. By default,
no processing in this function is added by the AppWizard, so if you want this function
in your application, you must add it to your application class through the Class
Wizard. (OnIdle is one of the available messages for the App class in your applications.)</P>
<P>The OnIdle function receives one argument, which is the number of times the OnIdle
function has been called since the last message was processed by your application.
You can use this to determine how long the application has been idle and when to
trigger any functionality that you need to run if the application is idle for more
than a certain amount of time.</P>
<P>One of the biggest concerns in adding OnIdle processing to your applications is
that any functionality you add must be small and must quickly return control to the
user. When an application performs any OnIdle processing, the user cannot interact
with the application until the OnIdle processing finishes and returns control to
the user. If you need to perform some long, drawn-out task in the OnIdle function,
break it up into many small and quick tasks so that control can return to the user;
then, you can continue your OnIdle task once the message queue is empty again. This
means that you also have to track your application's progress in the OnIdle task
so that the next time the OnIdle function is called, your application can pick up
the task where it left off.</P>
<P>
<H3><A NAME="Heading4"></A>Spawning Independent Threads</H3>
<P>If you really need to run a long background task that you don't want interfering
with the user, you should spawn an independent thread. A thread is like another application
running within your application. It does not have to wait until the application is
idle to perform its tasks, and it does not cause the user to wait until it takes
a break.</P>
<P>The two methods of creating an independent thread use the same function to create
and start the thread. To create and start an independent thread, you call the AfxBeginThread
function. You can choose to pass it a function to call for performing the thread's
tasks, or you can pass it a pointer to the runtime class for an object derived from
the CWinThread class. Both versions of the function return a pointer to a CWinThread
object, which runs as an independent thread.</P>
<P>In the first version of the AfxBeginThread function, the first argument is a pointer
to the main function for the thread to be started. This function is the equivalent
of the main function in a C/C++ program. It controls the top-level execution for
the thread. This function must be defined as a UINT function with a single LPVOID
argument:</P>
<P>
<PRE>UINT MyThreadFunction( LPVOID pParam);
</PRE>
<P>This version of the AfxBeginThread function also requires a second argument that
is passed along to the main thread function as the only argument to that function.
This argument can be a pointer to a structure containing any information that the
thread needs to know to perform its job correctly.</P>
<P>The first argument to the second version of the AfxBeginThread function is a pointer
to the runtime class of an object derived from the CWinThread class. You can get
a pointer to the runtime class of your CWinThread class by using the RUNTIME_CLASS
macro, passing your class as the only argument.</P>
<P>After these initial arguments, the rest of the arguments to the AfxBeginThread
function are the same for both versions, and they are all optional. The first of
these arguments is the priority to be assigned to the thread, with a default priority
of THREAD_PRIORITY_NORMAL. Table 18.1 lists the available thread priorities.</P>
<P>
<H4>TABLE 18.1. THREAD PRIORITIES.</H4>
<P>
<TABLE BORDER="1">
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT"><I>Priority</I></TD>
<TD ALIGN="LEFT"><I>Description</I></TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">0 </TD>
<TD ALIGN="LEFT">The thread will inherit the thread priority of the application creating the thread. </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">THREAD_PRIORITY_NORMAL </TD>
<TD ALIGN="LEFT">A normal (default) priority. </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">THREAD_PRIORITY_ABOVE_NORMAL </TD>
<TD ALIGN="LEFT">1 point above normal priority. </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">THREAD_PRIORITY_BELOW_NORMAL </TD>
<TD ALIGN="LEFT">1 point below normal priority. </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">THREAD_PRIORITY_HIGHEST </TD>
<TD ALIGN="LEFT">2 points above normal priority. </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">THREAD_PRIORITY_LOWEST </TD>
<TD ALIGN="LEFT">2 points below normal priority. </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">THREAD_PRIORITY_IDLE </TD>
<TD ALIGN="LEFT">Priority level of 1 for most threads (all non-real-time threads). </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">THREAD_PRIORITY_TIME_CRITICAL </TD>
<TD ALIGN="LEFT">Priority level of 15 for most threads (all non-real-time threads). </TD>
</TR>
</TABLE>
<BLOCKQUOTE>
<P>
<HR>
<STRONG>NOTE:</STRONG> Thread priority controls how much of the CPU's time the thread gets
in relation to the other threads and processes running on the computer. If a thread
will not be performing any tasks that need to be completed quickly, you should give
the thread a lower priority when creating it. It is not advisable to give a thread
a priority higher than normal unless it is vitally important that the thread perform
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -