??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品无码久久综合,精品国产青草久久久久福利,日韩精品久久无码人妻中文字幕http://www.shnenglu.com/dbkong/archive/2007/09/13/32162.htmlq_的天?/dc:creator>q_的天?/author>Thu, 13 Sep 2007 12:13:00 GMThttp://www.shnenglu.com/dbkong/archive/2007/09/13/32162.htmlhttp://www.shnenglu.com/dbkong/comments/32162.htmlhttp://www.shnenglu.com/dbkong/archive/2007/09/13/32162.html#Feedback0http://www.shnenglu.com/dbkong/comments/commentRss/32162.htmlhttp://www.shnenglu.com/dbkong/services/trackbacks/32162.html    当前行的Windows操作pȝ能同时运行几个程?独立q行的程序又UCE?Q对于同一个程序,它又可以分成若干个独立的执行,我们UC 为线E,U程提供了多d处理的能力。用q程和线E的观点来研IY件是当今普遍采用的方法,q程和线E的概念的出玎ͼҎ(gu)高Y件的q行性有着重要的意义? 现在的大型应用Y件无一不是多线E多d处理Q单U程的Y件是不可惌的。因此掌握多U程多Q务设计方法对每个E序员都是必需要掌握的。本实例针对多线E? 技术在应用中经帔R到的问题Q如U程间的通信、同步等Q分别进行探讨,q利用多U程技术进行线E之间的通信Q实C数字的简单排序。  

一?实现Ҏ(gu)

1、理解线E?br>
要讲解线E,不得不说一下进E,q程是应用程序的执行实例Q每个进E是q有的虚拟地址I间、代码、数据和其它pȝ资源l成。进E在q行时创建的资源 随着q程的终止而死亡。线E的基本思想很简单,它是一个独立的执行,是进E内部的一个独立的执行单元Q相当于一个子E序Q它对应于Visual C++中的CwinThreadcd象。单独一个执行程序运行时Q缺省地包含的一个主U程Q主U程以函数地址的Ş式出玎ͼ提供E序的启动点Q如main Q)或WinMainQ)函数{。当ȝE终止时Q进E也随之l止。根据实际需要,应用E序可以分解成许多独立执行的U程Q每个线Eƈ行的q行在同一q程 中?br>
一个进E中的所有线E都在该q程的虚拟地址I间中,使用该进E的全局变量和系l资源。操作系l给每个U程分配不同的CPU旉片,在某一个时刻, CPU只执行一个时间片内的U程Q多个时间片中的相应U程在CPU内轮执行,׃每个旉片时间很短,所以对用户来说Q仿佛各个线E在计算Z是ƈ行处 理的。操作系l是Ҏ(gu)U程的优先来安排CPU的时_优先U高的线E优先运行,优先U低的线E则l箋{待?br>
U程被分ZU:用户界面U程和工作线E(又称为后台线E)。用L面线E通常用来处理用户的输入ƈ响应各种事g和消息,其实Q应用程序的L行线E? CWinAPP对象是一个用L面线E,当应用程序启动时自动创徏和启动,同样它的l止也意味着该程序的l束Q进E终止。工作线E用来执行程序的后台? 理Q务,比如计算、调度、对串口的读写操作等Q它和用L面线E的区别是它不用从CWinThreadcL生来创徏Q对它来说最重要的是如何实现工作U程 d的运行控制函数。工作线E和用户界面U程启动时要调用同一个函数的不同版本Q最后需要读者明白的是,一个进E中的所有线E共享它们父q程的变量,但同 时每个线E可以拥有自q变量?

2、线E的理和操?br>
Q一Q线E的启动

创徏一个用L面线E,首先要从cCwinThread产生一个派生类Q同时必M用DECLARE_DYNCREATE? IMPLEMENT_DYNCREATE来声明和实现q个CwinThreadzcR第二步是根据需要重载该zcȝ一些成员函数如Q? ExitInstanceQ)、InitInstanceQ)、OnIdleQ)、PreTranslateMessageQ){函数。最后调? AfxBeginThread()函数的一个版本:CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ) 启动该用L面线E,其中W一个参Cؓ指向定义的用L面线E类指针变量Q第二个参数为线E的优先U,W三个参CؓU程所对应的堆栈大,W四个参CؓU? E创建时的附加标志,~省为正常状态,如ؓCREATE_SUSPENDED则线E启动后为挂L态?br>
对于工作U程来说Q启动一个线E,首先需要编写一个希望与应用E序的其余部分ƈ行运行的函数如Fun1()Q接着定义一个指向CwinThread? 象的指针变量*pThread,调用AfxBeginThread(Fun1,param,priority)函数Q返回DlpThread变量的同? 一q启动该U程来执行上面的Fun1Q)函数Q其中Fun1是线E要q行的函数的名字Q也既是上面所说的控制函数的名字,param是准备传送给U程函数 Fun1的Q?2位|priority则是定义该线E的优先U别Q它是预定义的常敎ͼ读者可参考MSDN?br>
Q二Q线E的优先U?br>
以下的CwinThreadcȝ成员函数用于U程优先U的操作Q?br>
////////////////////////////////////////////////////////////////
//////CtestView message handlers
/////Set to True to end thread
Bool bend=FALSE;//定义的全局变量Q用于控制线E的q行Q?br> //The Thread FunctionQ?br> UINT ThreadFunction(LPVOID pParam)//U程函数
{
while(!bend)
{
Beep(100,100);
Sleep(1000);
}
return 0;
}
/////////////////////////////////////////////////////////////
CwinThread *pThread;
HWND hWnd;
Void CtestView::OninitialUpdate()
{
hWnd=GetSafeHwnd();
pThread=AfxBeginThread(ThradFunction,hWnd);//启动U程
pThread->m_bAutoDelete=FALSE;//U程为手动删?br> Cview::OnInitialUpdate();
}
////////////////////////////////////////////////////////////////
Void CtestView::OnDestroy()
{
bend=TRUE;//改变变量Q线E结?br> WaitForSingleObject(pThread->m_hThread,INFINITE);//{待U程l束
delete pThread;//删除U程
Cview::OnDestroy();
}

  3、线E之间的通信

通常情况下,一个次U线E要ZU程完成某种特定cd的Q务,q就隐含着表示在主U程和次U线E之间需要徏立一个通信的通道。一般情况下Q有下面的几 U方法实现这U通信dQ用全局变量Q上一节的例子其实使用的就是这U方法)、用事件对象、用消息。这里我们主要介l后两种Ҏ(gu)?br>
Q一Q?利用用户定义的消息通信

在WindowsE序设计中,应用E序的每一个线E都拥有自己的消息队列,甚至工作U程也不例外Q这样一来,׃得线E之间利用消息来传递信息就变的 非常单。首先用戯定义一个用h息,如下所C:#define WM_USERMSG WMUSER+100Q在需要的时候,在一个线E中调用Q:PostMessage((HWND)param,WM_USERMSG,0,0)? CwinThread::PostThradMessageQ)来向另外一个线E发送这个消息,上述函数的四个参数分别是消息要发送到的目的窗口的? 柄、要发送的消息标志W、消息的参数WPARAM和LPARAM。下面的代码是对上节代码的修改,修改后的l果是在U程l束时显CZ个对话框Q提C线E结 束:

Retrun 0;
}
  上面的例子是工作者线E向用户界面U程发送消息,对于工作者线E,如果它的设计模式也是消息驱动的,那么调用者可以向它发送初始化、退 出、执行某U特定的处理{消息,让它在后台完成。在控制函数中可以直接用:QGetMessage()q个SDK函数q行消息分检和处理,自己实现一? 消息循环。GetMessage()函数在判断该U程的消息队列ؓI时Q线E将pȝ分配l它的时间片让给其它U程Q不无效的占用CPU的时_如果消息? 列不为空Q就获取q个消息Q判断这个消息的内容q进行相应的处理?br>
Q二Q用事g对象实现通信

在线E之间传递信可行通信比较复杂的方法是使用事g对象Q用MFC的Ceventcȝ对象来表C。事件对象处于两U状态之一Q有信号和无信号Q线E可以监视处于有信号状态的事gQ以便在适当的时候执行对事g的操作。上qC子代码修改如下:

while(!bend)
{
Beep(100,100);
Sleep(1000);
Int result=::WaitforSingleObject(threadEnd.m_hObject,0);
//{待threadEnd事g有信P无信hU程在这里?zhn)?br> If(result==Wait_OBJECT_0)
Bend=TRUE;
}
Q:PostMessage(hWnd,WM_USERMSG,0,0)Q?br> return 0;
}
/////////////////////////////////////////////////////////////
Void CtestView::OninitialUpdate()
{
hWnd=GetSafeHwnd();
threadStart.SetEvent();//threadStart事g有信?br> pThread=AfxBeginThread(ThreadFunction,hWnd);//启动U程
pThread->m_bAutoDelete=FALSE;
Cview::OnInitialUpdate();
}
////////////////////////////////////////////////////////////////
Void CtestView::OnDestroy()
{
threadEnd.SetEvent();
WaitForSingleObject(pThread->m_hThread,INFINITE);
delete pThread;
Cview::OnDestroy();
}
  q行q个E序Q当关闭E序Ӟ才显C提C框Q显C?Thread ended"?

  4、线E之间的同步

前面我们讲过Q各个线E可以访问进E中的公共变量,所以用多U程的过E中需要注意的问题是如何防止两个或两个以上的线E同时访问同一个数据,以免? 坏数据的完整性。保证各个线E可以在一起适当的协调工作称为线E之间的同步。前面一节介l的事g对象实际上就是一U同步Ş式。Visual C++中用同步类来解x作系l的q行性而引L数据不安全的问题QMFC支持的七个多U程的同步类可以分成两大c:同步对象 QCsyncObject、Csemaphore、Cmutex、CcriticalSection和CeventQ和同步讉K对象 QCmultiLock和CsingleLockQ。本节主要介l界区Qcritical sectionQ、互斥(mutexeQ、信号量QsemaphoreQ,q些同步对象使各个线E协调工作,E序q行h更安全?br>
Q一Q?临界?br>
临界区是保证在某一个时间只有一个线E可以访问数据的Ҏ(gu)。用它的过E中Q需要给各个U程提供一个共享的临界区对象,无论哪个U程占有临界区对象, 都可以访问受C护的数据Q这时候其它的U程需要等待,直到该线E释放界区对象为止Q界区被释攑֐Q另外的U程可以强占q个临界区,以便讉K׃n的数 据。界区对应着一个CcriticalSection对象Q当U程需要访问保护数据时Q调用界区对象的Lock()成员函数Q当对保护数据的操作完成 之后Q调用界区对象的Unlock()成员函数释放对界区对象的拥有权Q以使另一个线E可以夺取界区对象q访问受保护的数据。同时启动两个线E,? 们对应的函数分别为WriteThread()和ReadThread()Q用以对公共数组larray[]操作Q下面的代码说明了如何用界区对象Q?br>
int array[10],destarray[10];
CCriticalSection Section;
UINT WriteThread(LPVOID param)
{
Section.Lock();
for(int x=0;x<10;x++)
array[x]=x;
Section.Unlock();
}
UINT ReadThread(LPVOID param)
{
Section.Lock();
For(int x=0;x<10;x++)
Destarray[x]=array[x];
Section.Unlock();
}
  上述代码q行的结果应该是Destarray数组中的元素分别?-9Q而不是杂乱无章的敎ͼ如果不用同步,则不是这个结果,有兴的读者可以实验一下?br>
Q二Q互?br>
互斥与界区很相|但是使用时相对复杂一些,它不仅可以在同一应用E序的线E间实现同步Q还可以在不同的q程间实现同步,从而实现资源的安全׃n? 互斥与Cmutexcȝ对象相对应,使用互斥对象Ӟ必须创徏一个CSingleLock或CMultiLock对象Q用于实际的讉K控制Q因里的? 子只处理单个互斥Q所以我们可以用CSingleLock对象Q该对象的Lock()函数用于占有互斥QUnlock()用于释放互斥。实C码如下:

int array[10],destarray[10];
CMutex Section;

UINT WriteThread(LPVOID param)
{
CsingleLock singlelock;
singlelock (&Section);
singlelock.Lock();
for(int x=0;x<10;x++)
array[x]=x;
singlelock.Unlock();
}

UINT ReadThread(LPVOID param)
{
CsingleLock singlelock;
singlelock (&Section);
singlelock.Lock();
For(int x=0;x<10;x++)
Destarray[x]=array[x];
singlelock.Unlock();
}
  Q三Q信号量

信号量的用法和互斥的用法很相|不同的是它可以同一时刻允许多个U程讉K同一个资源,创徏一个信号量需要用Csemaphorecd明一个对象,一 旦创Z一个信号量对象Q就可以用它来对资源的访问技术。要实现计数处理Q先创徏一个CsingleLock或CmltiLock对象Q然后用该对象的 Lock()函数减少q个信号量的计数|Unlock()反之。下面的代码分别启动三个U程Q执行时同时昄二个消息框,然后10U后W三个消息框才得 以显C?br>
return 0;
}
UINT ThreadProc2(LPVOID param)
{
CSingleLock singelLock(semaphore);
singleLock.Lock();
Sleep(10000);
::MessageBox((HWND)param,"Thread2 had access","Thread2",MB_OK);
return 0;
}

UINT ThreadProc3(LPVOID param)
{
CsingleLock singelLock(semaphore);
singleLock.Lock();
Sleep(10000);
::MessageBox((HWND)param,"Thread3 had access","Thread3",MB_OK);
return 0;
}
  二?~程步骤

1?启动Visual C++6.0Q生成一?2位的控制台程序,该E序命名?sequence"

2?输入要排l的数字Q声明四个子U程Q?br>
3?输入代码Q编译运行程序?/p>

三?E序代码

#include "stdlib.h"
#include "memory.h"
HANDLE evtTerminate; //事g信号,标记是否所有子U程都执行完
/*
下面使用了三U控制方法,你可以注释其中两U,使用其中一U?br> 注意修改时要q带修改临界区PrintResult里的相应控制语句
*/
HANDLE evtPrint; //事g信号,标记事g是否已发?br> //CRITICAL_SECTION csPrint; //临界?br> //HANDLE mtxPrint; //互斥信号,如有信号表明已经有线E进入界区q拥有此信号
static long ThreadCompleted = 0;
/*用来标记四个子线E中已完成线E的个数,当一个子U程完成时就对ThreadCompletedq行加一操作, 要用InterlockedIncrement(long* lpAddend)和InterlockedDecrement(long* lpAddend)q行加减操作*/

//下面的结构是用于传送排序的数据l各个排序子U程
struct MySafeArray
{
long* data;
int iLength;
};

//打印每一个线E的排序l果
void PrintResult(long* Array, int iLength, const char* HeadStr = "sort");

//排序函数
unsigned long __stdcall BubbleSort(void* theArray); //冒排序
unsigned long __stdcall SelectSort(void* theArray); //选择排序
unsigned long __stdcall HeapSort(void* theArray); //堆排?br> unsigned long __stdcall InsertSort(void* theArray); //插入排序
/*以上四个函数的声明必适合作ؓ一个线E函数的必要条g才可以用CreateThread
建立一个线E?br> Q?Q调用方法必L__stdcallQ即函数参数压栈序由右到左Q而且由函数本w负?br> 栈的恢复, C和C++默认是__cdecl, 所以要昑ּ声明是__stdcall
Q?Q返回值必Lunsigned long
Q?Q参数必L一?2位|如一个指针值或longcd
(4) 如果函数是类成员函数Q必d明ؓstatic函数Q在CreateThread时函数指针有Ҏ(gu)的写法。如?函数是类CThreadTest的成员函C)Q?br> static unsigned long _stdcall MyThreadFun(void* pParam);
handleRet = CreateThread(NULL, 0, &CThreadTestDlg::MyThreadFun, NULL, 0, &ThreadID);
之所以要声明为static是由于,该函数必要独立于对象实例来使用Q即使没有声明实例也可以使用?/

int QuickSort(long* Array, int iLow, int iHigh); //快速排?br>
int main(int argc, char* argv[])
{
long data[] = {123,34,546,754,34,74,3,56};
int iDataLen = 8;
//Z对各个子U程分别对原始数据进行排序和保存排序l果
//分别分配内存对data数组的数据进行复?br> long *data1, *data2, *data3, *data4, *data5;
MySafeArray StructData1, StructData2, StructData3, StructData4;
data1 = new long[iDataLen];
memcpy(data1, data, iDataLen << 2); //把data中的数据复制到data1?br> //内存复制 memcpy(目标内存指针, 源内存指? 复制字节?, 因ؓlong的长?br> //?字节,所以复制的字节CؓiDataLen << 2, 即等于iDataLen*4
StructData1.data = data1;
StructData1.iLength = iDataLen;
data2 = new long[iDataLen];
memcpy(data2, data, iDataLen << 2);
StructData2.data = data2;
StructData2.iLength = iDataLen;
data3 = new long[iDataLen];
memcpy(data3, data, iDataLen << 2);
StructData3.data = data3;
StructData3.iLength = iDataLen;
data4 = new long[iDataLen];
memcpy(data4, data, iDataLen << 2);
StructData4.data = data4;
StructData4.iLength = iDataLen;
data5 = new long[iDataLen];
memcpy(data5, data, iDataLen << 2);
unsigned long TID1, TID2, TID3, TID4;
//对信号量q行初始?br> evtTerminate = CreateEvent(NULL, FALSE, FALSE, "Terminate");
evtPrint = CreateEvent(NULL, FALSE, TRUE, "PrintResult");
//分别建立各个子线E?br> CreateThread(NULL, 0, &BubbleSort, &StructData1, NULL, &TID1);
CreateThread(NULL, 0, &SelectSort, &StructData2, NULL, &TID2);
CreateThread(NULL, 0, &HeapSort, &StructData3, NULL, &TID3);
CreateThread(NULL, 0, &InsertSort, &StructData4, NULL, &TID4);
//在主U程中执行行快速排序,其他排序在子U程中执?
QuickSort(data5, 0, iDataLen - 1);
PrintResult(data5, iDataLen, "Quick Sort");
WaitForSingleObject(evtTerminate, INFINITE); //{待所有的子线E结?br> //所有的子线E结束后Q主U程才可以结?br> delete[] data1;
delete[] data2;
delete[] data3;
delete[] data4;
CloseHandle(evtPrint);
return 0;
}

/*
冒排序思想(升序Q降序同理,后面的算法一样都是升?:从头到尾Ҏ(gu)据进行两两比较进行交?的攑։大的攑֐。这样一ơ下来,最大的元素׃被交换的最后,然后下一?
循环׃用对最后一个元素进行比较交换了Q所以呢每一ơ比较交换的ơ数都比上一ơ@环的ơ数一Q这样Nơ之后数据就变得升序排列?/
unsigned long __stdcall BubbleSort(void* theArray)
{
long* Array = ((MySafeArray*)theArray)->data;
int iLength = ((MySafeArray*)theArray)->iLength;
int i, j=0;
long swap;
for (i = iLength-1; i >0; i--)
{
for(j = 0; j < i; j++)
{
if(Array[j] >Array[j+1]) //前比后大Q交?br> {
swap = Array[j];
Array[j] = Array[j+1];
Array[j+1] = swap;
}
}
}
PrintResult(Array, iLength, "Bubble Sort"); //向控制台打印排序l果
InterlockedIncrement(&ThreadCompleted); //q回前ɾU程完成数标记加1
if(ThreadCompleted == 4) SetEvent(evtTerminate); //查是否其他线E都已执行完
//若都执行完则讄E序l束信号?br> return 0;
}

/*选择排序思想:每一ơ都从无序的数据中找出最的元素Q然后和前面已经有序的元素序列的后一个元素进行交换,q样整个源序列就会分成两部分Q前面一? 分是已经排好序的有序序列Q后面一部分是无序的Q用于选出最的元素。@环Nơ之后,前面的有序序列加长到跟源序列一样长Q后面的无序部分长度变ؓ0Q排 序就完成了?/
unsigned long __stdcall SelectSort(void* theArray)
{
long* Array = ((MySafeArray*)theArray)->data;
int iLength = ((MySafeArray*)theArray)->iLength;
long lMin, lSwap;
int i, j, iMinPos;
for(i=0; i < iLength-1; i++)
{
lMin = Array[i];
iMinPos = i;
for(j=i + 1; j <= iLength-1; j++) //从无序的元素中找出最的元素
{
if(Array[j] < lMin)
{
iMinPos = j;
lMin = Array[j];
}
}
//把选出的元素交换拼接到有序序列的最?br> lSwap = Array[i];
Array[i] = Array[iMinPos];
Array[iMinPos] = lSwap;
}
PrintResult(Array, iLength, "Select Sort"); //向控制台打印排序l果
InterlockedIncrement(&ThreadCompleted); //q回前ɾU程完成数标记加1
if(ThreadCompleted == 4) SetEvent(evtTerminate);//查是否其他线E都已执行完
//若都执行完则讄E序l束信号?br> return 0;
}

/*堆排序思想Q堆Q数据元素从1到N排列成一二叉树Q而且q棵树的每一个子树的栚w是该树中的元素的最或最大的元素q样如果一个无序数据集合是一? 堆那么,根元素就是最或最大的元素堆排序就是不断对剩下的数据徏堆,把最或最大的元素析透出来。下面的法Q就是从最后一个元素开始,依据一个节Ҏ(gu) 父节Ҏ(gu)值大的原则对所有元素进行调_q样调整一ơ就形成一个堆Q第一个元素就是最的元素。然后再对剩下的无序数据再进行徏堆,注意q时后面的无序数 据元素的序数都要改变Q如W一ơ徏堆后Q第二个元素׃变成堆的W一个元素?/
unsigned long __stdcall HeapSort(void* theArray)
{
long* Array = ((MySafeArray*)theArray)->data;
int iLength = ((MySafeArray*)theArray)->iLength;
int i, j, p;
long swap;
for(i=0; i {
for(j = iLength - 1; j>i; j--) //从最后倒数上去比较字节点和父节?br> {
p = (j - i - 1)/2 + i; //计算父节Ҏ(gu)l下?br> //注意到树节点序数跟数l下标不是等同的Q因为徏堆的元素个数逐个递减
if(Array[j] < Array[p]) //如果父节Ҏ(gu)值大则交换父节点和字节点
{
swap = Array[j];
Array[j] = Array[p];
Array[p] = swap;
}
}
}
PrintResult(Array, iLength, "Heap Sort"); //向控制台打印排序l果
InterlockedIncrement(&ThreadCompleted); //q回前ɾU程完成数标记加1
if(ThreadCompleted == 4) SetEvent(evtTerminate); //查是否其他线E都已执行完
//若都执行完则讄E序l束信号?br> return 0;
}

/*插入排序思想Q把源数据序列看成两半,前面一半是有序的,后面一半是无序的,把无序的数据从头到尾逐个逐个的插入到前面的有序数据中Q得有序的数据的个C断增大,同时无序的数据个数就来少Q最后所有元素都会变得有序?/
unsigned long __stdcall InsertSort(void* theArray)
{
long* Array = ((MySafeArray*)theArray)->data;
int iLength = ((MySafeArray*)theArray)->iLength;
int i=1, j=0;
long temp;
for(i=1; i {
temp = Array[i]; //取出序列后面无序数据的第一个元素?br> for(j=i; j>0; j--) //和前面的有序数据逐个q行比较扑և合适的插入位置
{
if(Array[j - 1] >temp) //如果该元素比插入值大则后U?br> Array[j] = Array[j - 1];
else //如果该元素比插入值小Q那么该位置的后一位就是插入元素的位置
break;
}
Array[j] = temp;
}
PrintResult(Array, iLength, "Insert Sort"); //向控制台打印排序l果
InterlockedIncrement(&ThreadCompleted); //q回前ɾU程完成数标记加1
if(ThreadCompleted == 4) SetEvent(evtTerminate); //查是否其他线E都已执行完
//若都执行完则讄E序l束信号?br> return 0;
}

/*快速排序思想Q快速排序是分治思想的一U应用,它先选取一个支点,然后把小于支点的元素交换到支点的前边Q把大于支点的元素交换到支点的右辏V然后再Ҏ(gu)点左辚w分和?br> 辚w分进行同L处理Q这栯q次之后Q数据就会变得有序。下面的实现使用了递归
建立两个游标QiLowQiHighQiLow指向序列的第一个元素,iHigh指向最后一个先选第一个元素作为支点,q把它的值存贮在一个辅助变量里? 那么W一个位|就变ؓIƈ可以攄其他的元素? q样从iHigh指向的元素开始向前移动游标,iHigh查找比支点小的元素,如果扑ֈQ则把它攄到空|了的位|(现在是第一个位|)Q然后iHigh 游标停止UdQ这时iHigh指向的位|被I置Q然后移动iLow游标L比支点大的元素放|到iHigh指向的空|的位置Q如此往复直到iLow? iHigh相等。最后用递归对左右两部分q行同样处理*/

int QuickSort(long* Array, int iLow, int iHigh)
{
if(iLow >= iHigh) return 1; //递归l束条g
long pivot = Array[iLow];
int iLowSaved = iLow, iHighSaved = iHigh; //保未改变的iLowQiHighg存v?br> while (iLow < iHigh)
{
while (Array[iHigh] >= pivot && iHigh >iLow) //L比支点大的元?br> iHigh -- ;
Array[iLow] = Array[iHigh]; //把找到的元素攄到空|的位置
while (Array[iLow] < pivot && iLow < iHigh) //L比支点小的元?br> iLow ++ ;
Array[iHigh] = Array[iLow]; //把找到的元素攄到空|的位置
}
Array[iLow] = pivot; //把支点值放|到支点位置Q这时支点位|是I置?br> //对左右部分分别进行递归处理
QuickSort(Array, iLowSaved, iHigh-1);
QuickSort(Array, iLow+1, iHighSaved);
return 0;
}

//每一个线E都要用这个函数进行输出,而且只有一个显C器Q生多个线E?br> //竞争Ҏ(gu)制台的用权?br> void PrintResult(long* Array, int iLength, const char* HeadStr)
{
WaitForSingleObject(evtPrint, INFINITE); //{待事g有信?br> //EnterCriticalSection(&csPrint); //标记有线E进入界区
//WaitForSingleObject(mtxPrint, INFINITE); //{待互斥量空|(没有U程拥有它)
int i;
printf("%s: ", HeadStr);
for (i=0; i {
printf("%d,", Array[i]);
Sleep(100); //延时Q可以去掉)
/*只是使得多线E对临界问的问题比较Ҏ(gu)看得?br> 如果你把临界控制的语句注释掉Q输出就会变得很凌ؕQ各个排序的l果?br> 分插间隔着输出Q如果不延时׃Ҏ(gu)看到q种不对临界区控制的l果
*/
}
printf("%d\n", Array[i]);
SetEvent(evtPrint); //把事件信号量恢复Q变为有信号
}
  四?结

对复杂的应用E序来说Q线E的应用l应用程序提供了高效、快速、安全的数据处理能力。本实例讲述了线E处理中l常遇到的问题,希望对读者朋友有一定的帮助Qv到抛砖引玉的作用?/p>

转自Qhttp://hi.baidu.com/laodun/blog/item/8ab8f3241af3f7318644f916.htmlQ?/p>

]]>
我的c设计复查表http://www.shnenglu.com/dbkong/archive/2007/04/17/22138.htmlq_的天?/dc:creator>q_的天?/author>Tue, 17 Apr 2007 08:44:00 GMThttp://www.shnenglu.com/dbkong/archive/2007/04/17/22138.htmlhttp://www.shnenglu.com/dbkong/comments/22138.htmlhttp://www.shnenglu.com/dbkong/archive/2007/04/17/22138.html#Feedback0http://www.shnenglu.com/dbkong/comments/commentRss/22138.htmlhttp://www.shnenglu.com/dbkong/services/trackbacks/22138.html需要构造器吗?
  • 数据成员是private的吗Q它可以是const的吗Q?
  • 需要默认构造器吗?
  • 是不是每个构造器初始化了所有成员?
  • 需要析构器吗?它需要虚化吗Q?
  • 需要拷贝构造器吗?
  • 需要assigment operator吗?它能正确自赋值吗Q?
  • 需要关pL作符吗?
  • 在函数Ş参上使用了const吗?在成员函C后呢Q?
  • 删除数组成员时用delete []吗?


  • ]]>
    操作W重载的位置选择Q选择成员或非成员Q?/title><link>http://www.shnenglu.com/dbkong/archive/2007/04/13/21772.html</link><dc:creator>q_的天?/dc:creator><author>q_的天?/author><pubDate>Fri, 13 Apr 2007 03:40:00 GMT</pubDate><guid>http://www.shnenglu.com/dbkong/archive/2007/04/13/21772.html</guid><wfw:comment>http://www.shnenglu.com/dbkong/comments/21772.html</wfw:comment><comments>http://www.shnenglu.com/dbkong/archive/2007/04/13/21772.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/dbkong/comments/commentRss/21772.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/dbkong/services/trackbacks/21772.html</trackback:ping><description><![CDATA[<p>1.赋?Q?,下标([]),调用( () )和成员访问箭?->){操作符必须定义为成?这些定义ؓ非成员函数将在编译时标记为错?/p> 2.像赋g?复合赋值操作符通常应定义ؓcȝ成员,与赋g同的?不一定非得这样做,如果定义非成员复合赋值操作符,不会出现~译错误.<br>3.改变对象状态或与给类型紧密联pȝ其他一些操作符,如自?自减和自解引?通常应定义ؓcL?br>4.对称的操作符?如算术操作符,相等操作W?关系操作W和位操作符,最好定义ؓ普通非成员函数. <img src ="http://www.shnenglu.com/dbkong/aggbug/21772.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/dbkong/" target="_blank">q_的天?/a> 2007-04-13 11:40 <a href="http://www.shnenglu.com/dbkong/archive/2007/04/13/21772.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>定义默认实参的约?/title><link>http://www.shnenglu.com/dbkong/archive/2007/04/13/21769.html</link><dc:creator>q_的天?/dc:creator><author>q_的天?/author><pubDate>Fri, 13 Apr 2007 02:43:00 GMT</pubDate><guid>http://www.shnenglu.com/dbkong/archive/2007/04/13/21769.html</guid><wfw:comment>http://www.shnenglu.com/dbkong/comments/21769.html</wfw:comment><comments>http://www.shnenglu.com/dbkong/archive/2007/04/13/21769.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/dbkong/comments/commentRss/21769.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/dbkong/services/trackbacks/21769.html</trackback:ping><description><![CDATA[既可以在函数声明也可以在函数定义中指定默认实?但是在一个文件中,只能Z个Ş参指定默认实参一ơ下面的例子是错误的,<br>//ff.h<br>int ff(int=0);<br>//ff.cc<br>#include "ff.h"<br>int ff(int i=0){}//error<br>如果在函数定义的形参表中提供默认实参,那么只有在包含该函数定义的源文g中调用该函数?默认实参才是有效? <img src ="http://www.shnenglu.com/dbkong/aggbug/21769.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/dbkong/" target="_blank">q_的天?/a> 2007-04-13 10:43 <a href="http://www.shnenglu.com/dbkong/archive/2007/04/13/21769.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么时候必M用初始化列表http://www.shnenglu.com/dbkong/archive/2007/04/10/21586.htmlq_的天?/dc:creator>q_的天?/author>Tue, 10 Apr 2007 04:01:00 GMThttp://www.shnenglu.com/dbkong/archive/2007/04/10/21586.htmlhttp://www.shnenglu.com/dbkong/comments/21586.htmlhttp://www.shnenglu.com/dbkong/archive/2007/04/10/21586.html#Feedback0http://www.shnenglu.com/dbkong/comments/commentRss/21586.htmlhttp://www.shnenglu.com/dbkong/services/trackbacks/21586.html1.没有默认构造函数的cȝ型的成员(q是因ؓ构造函数分Z个阶D?1.初始化阶D?2.普通计阶D?初始化阶D发生在计算阶段开始之?
    2.成员为const或引用类?
     

    ]]>
    前向声明http://www.shnenglu.com/dbkong/archive/2007/04/09/21566.htmlq_的天?/dc:creator>q_的天?/author>Mon, 09 Apr 2007 15:24:00 GMThttp://www.shnenglu.com/dbkong/archive/2007/04/09/21566.htmlhttp://www.shnenglu.com/dbkong/comments/21566.htmlhttp://www.shnenglu.com/dbkong/archive/2007/04/09/21566.html#Feedback3http://www.shnenglu.com/dbkong/comments/commentRss/21566.htmlhttp://www.shnenglu.com/dbkong/services/trackbacks/21566.html   可以声明一个类而不定义?br>   class Screen;//declaration of the Screen class
       q个声明,有时候被UCؓ前向声明(forward declaration),在程序中引入了类cd的Screen.在声明之?定义之前,cScreen是一个不完全cd(incompete type),卛_知Screen是一个类?但不知道包含哪些成员.
       不完全类型只能以有限方式使用,不能定义该类型的对象,不完全类型只能用于定义指向该cd的指针及引用,或者用于声?而不是定?使用该类型作为Ş参类型或q回cd的函?



    ]]>
    PostMessage与SendMessage的区?/title><link>http://www.shnenglu.com/dbkong/archive/2007/03/09/19480.html</link><dc:creator>q_的天?/dc:creator><author>q_的天?/author><pubDate>Fri, 09 Mar 2007 03:31:00 GMT</pubDate><guid>http://www.shnenglu.com/dbkong/archive/2007/03/09/19480.html</guid><wfw:comment>http://www.shnenglu.com/dbkong/comments/19480.html</wfw:comment><comments>http://www.shnenglu.com/dbkong/archive/2007/03/09/19480.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.shnenglu.com/dbkong/comments/commentRss/19480.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/dbkong/services/trackbacks/19480.html</trackback:ping><description><![CDATA[ <font size="2">PostMessage</font> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">只是把消息放入队列,不管其他E序是否处理都返回,然后l箋执行</span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">;<br /></font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">?/span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">SendMessage</font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">必须{待其他E序处理消息后才q回Ql执行?/span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <br /> <font face="Times New Roman">PostMessage</font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">的返回DC?/span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">PostMessage</font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">函数执行是否正确</span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">;<br /></font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">?/span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">SendMessage</font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">的返回DC其他程序处理消息后的返回倹{?/span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman"> <br /> </font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">使用q两个发送消息函数的最重要的是要看你的E序是否要对消息的滞后性关注否</span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">,PostMessage</font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">会造成消息的滞后?/span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">,</font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">?/span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">SendMessage</font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">则不?/span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">,</font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">但如?/span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">SendMessage</font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">消息处理p|</span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">,</font> </span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-ascii-font-family: ˎ̥; mso-hansi-font-family: ˎ̥">则会造成E序停止</span> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: ˎ̥; mso-bidi-font-family: Tahoma"> <font face="Times New Roman">!<?XML:NAMESPACE PREFIX = O /?><o:p></o:p></font> </span> <img src ="http://www.shnenglu.com/dbkong/aggbug/19480.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/dbkong/" target="_blank">q_的天?/a> 2007-03-09 11:31 <a href="http://www.shnenglu.com/dbkong/archive/2007/03/09/19480.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MFC消息详解http://www.shnenglu.com/dbkong/archive/2007/03/09/19479.htmlq_的天?/dc:creator>q_的天?/author>Fri, 09 Mar 2007 03:22:00 GMThttp://www.shnenglu.com/dbkong/archive/2007/03/09/19479.htmlhttp://www.shnenglu.com/dbkong/comments/19479.htmlhttp://www.shnenglu.com/dbkong/archive/2007/03/09/19479.html#Feedback0http://www.shnenglu.com/dbkong/comments/commentRss/19479.htmlhttp://www.shnenglu.com/dbkong/services/trackbacks/19479.html转蝲?a >http://blog.csdn.net/Image_Graphics/archive/2006/11/22/1405436.aspx


    1. 怎样使用MFC发送一个消息用MFC发送一个消息的Ҏ(gu)是,
        首先Q应获取接收消息的CWndcd象的指针Q?br />    然后,调用CWnd的成员函数SendMessage( )?br />        LRESULT Res=pWnd->SendMessage(UINT Msg, WPARAM wParam, LPARAM lParam);
            pWnd指针指向目标CWndcd象。变量Msg是消息,wParam和lParam变量包含消息的参敎ͼ如鼠标单d里或选择了什么菜单项。目标窗口返回的消息l果攑֜变量Res中?br />        发送消息到一个没有CWndcd象的H口Q可以用下列目标H口的句柄直接调用Windows APIQ?br />        LRESULT Res=::SendMessage(HWND hWnd, UINT Msg,  WPARAM wParam, LPARAM lParam);
            q里的hWnd是目标窗口的句柄?br />2. 怎样用MFC寄送一个消?br />    用MFC寄送一个消息与发送一个消息几乎相同,但寄送时用PostMessage( ) Q而不是用SendMessage( )Q返回值Res也不一PRes不是一个由目标H口q回的|而是一个布?yu)|用来表示消息是否成功地放到消息队列中?br />3. 索一个寄送消?br />    正常情况下,一旦消息被寄送后Q应用程序在后台发送它。但是在Ҏ(gu)情况下,需要你自己d除一个消息,例如惛_应用E序接收到某U消息之前停止应用程序。有两种Ҏ(gu)可以从应用程序消息队列中删除一个消息,但这两种Ҏ(gu)都没有涉及MFC?br />?W一U方法:在不q扰M事情之下H视消息队列Q看看一个消息是否在那里?br />    BOOL res=::PeekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg ) ;
    ?W二U方法:实际上是{待Q一直等C个新的消息到N列ؓ止,然后删除q返回该消息?br />    BOOL res=::GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
        在这两种Ҏ(gu)中,变量hWnd指定要截h息的H口Q如果该变量设ؓNULLQ所有窗口消息将被截莗wMsgFilterMin和wMsgFilterMax变量与SendMessage( )中的变量Msg相对应,指定查看消息的范围。如果用"0,0"Q则所有的消息都将被截莗如果用WM_KEYFIRST,WM_KEYLAST或WM_MOUSEFIRST,WM_MOUSELASTQ则所有键盘或鼠标的消息将被截莗wRemoveMsg变量指定PeekMessage( )是否应该真正C队列中删除该消息?GetMessage( )L删除消息)。该变量可以取两个|
        ?PM_REMOVEQPeekMessage( )删除消息?br />    ?PM_NOREMOVEQPeekMessage( )把消息留在队列里,q返回它的一个拷贝?br />    当然Q如果把消息留在消息队列中,然后再次调用PeekMessage( )查看相同cd的消息,则将q回完全相同的消息?br />    lpMsg变量是一个指向MSGl构的指针,MSG包含索到的消息?br />    typedef struct tagMSG {
                            HWND hwnd; // window handle message is intended for
                            UINT message;
                            WPARAM wParam;
                            LPARAM lParam;
                            DWORD time; // the time the message was put in the queue
                            POINT pt; // the location of the mouse cursor when the
                                           // message was put in the queue
                            } MSG;
    4. MFC怎样接收一个寄送的消息
        MFC处理一个寄送和发送消息的唯一明显不同是寄送的消息要在应用E序的消息队列中p一些时间。在消息?message pump)弹出它之前,它要一直在队列中?br />    消息?br />    MFC应用E序中的消息泵在CWinApp的成员函数Run()中。应用程序开始运行时QRun()p调用,Run()把时间分割成两部分。一部分用来执行后台处理Q如取消临时CWnd对象Q另一部分用来查消息队列。当一个新的消息进来时QRun()抽取它—即用GetMessage( )从队列中取出该消息,q行两个消息译函数Q然后用DispatchMessage( )函数调用该消息预期的目标H口q程?br />    消息泵调用的两个译函数是PreTranslateMessage( )?:TranslateMessage( )。目标窗口的MFCcd调用reTranslateMessage在发送消息给它之前进行消息翻译,例如QCFrameWnd用PreTranslateMessage( )加速键(如,Ctrl+S存储文g)转换为命令消息。翻译前的消息通常被处理掉Q而翻译后的消?如果有的?被重新寄送到队列里?:TranslateMessage是一个窗口函敎ͼ原始键码{换ؓ键字W。消息一旦被DispatchMessage()发送,MFC处理它就像处理SendMessage()发送的消息一栗?br />5. MFC怎样处理一个接收到的消?br />    处理接收到的消息的目的非常简单:消息指向一个函敎ͼ该函数通过消息中的消息标识W处理它。非MFCH口用简单的case语句来实现该目标Q每个case语句执行一些函敎ͼ或调用其他一些函数?br />    MainWndProc(HWND hWnd, UINT message, W PARAM wParam,LPARAM lParam)
        {
            switch(message)
            {
            case WM_CREATE:
                : : :
            break;
            case WM_PAINT:
                : : :
            break;
            default:
            return(DefWindowProc(hWnd,message,wParam,lParam));
            }
            return(NULL);
        }
        M遗漏的消息将被传输到一个默认的消息处理函数Q但是,case语句不能很好地适应C++和封装技术。在C++环境中,要求消息被一个专门处理该cd消息的类的成员函数处理。因此,MFC不采用case语句Q而采用更加复杂和回旋的方法。但它允许用U有cd理消息,而只需做下面三件事情:
        ?从将要接收消息的CWndcd象派生类(对于命o消息是CCmdTarget)?br />    ?在派生类中写一个处理消息的成员函数?br />    ?在类中定义一个查找表(叫做消息映像)Q该表具有成员函数的条目和它要处理的消息的标识符?br />    然后QMFC依次调用下面的函敎ͼ指引输入消息到处理函数?br />    1) AfxWndProc( )接收消息Q寻找消息所属的CWnd对象Q然后调用AfxCallWndProc( )?br />    2) AfxCallWndProc( )存储消息(消息标识W和参数)供未来参考,然后调用WindowProc( )?br />    3) WindowProc( ) 发送消息给OnWndMsg( ) Q然后,如果消息未被处理Q则发送给DefWindowproc( )?br />    4) OnWndMsg( )要么为WM_COMMAND消息调用OnCommand( )Q要么ؓWM_NOTIFY消息调用OnNotify( )。Q何被遗漏的消息都是一个窗口消息。OnWndMsg( )搜烦cȝ消息映像Q以扑ֈ一个能处理MH口消息的处理函数。如果OnWndMsg( )不能扑ֈq样的处理函敎ͼ则把消息q回到WindowProc( )Q由它将消息发送给DefWindowProc( )?br />    5) OnCommand()查看q是不是一个控仉知(lParam不是NULL)Q如果它是,OnCommand( )p囑ְ消息映射到制造通知的控Ӟ如果它不是一个控仉知Q或者控件拒l映的消息QOnCommand( )p用OnCmdMsg( )?br />    6) OnNotify( )也试囑ְ消息映射到制造通知的控Ӟ如果映射不成功, OnNotify( )p用相同的OnCmdMsg( )函数?br />    7) Ҏ(gu)接收消息的类QOnCmdMsg( )在一个称为命令传?Command Routing)的过E中潜在C递命令消息和控g通知。例如,如果拥有该窗口的cL一个框架类Q则命o和通知消息也被传递到视图和文档类Qƈcd找一个消息处理函数?br />Z么要消息映像Q?br />    q毕竟是C++语言Qؓ什么OnWndMsg( )不ؓ每个H口消息调用一个预定义的虚拟函敎ͼ因ؓ它太占CPU。若是那P当扫描一个消息映像以加速该q程ӞOnWndMsg( )可能会做出意想不到的事情Qƈ陷入汇编器。注意通过重蝲WindowProc( )、OnWndMsg( )、OnCommand( )、OnNotify( ) 或OnCmdMsg( )可以修改q一q程。重载OnWndMsg( )可以在窗口消息被排序之前插入该过E。重载OnCommand( )或OnNotify( )可以在消息被反射之前插入该过E?/p>

    ]]>
    C#中File与FileInfo的区?/title><link>http://www.shnenglu.com/dbkong/archive/2007/03/06/19310.html</link><dc:creator>q_的天?/dc:creator><author>q_的天?/author><pubDate>Tue, 06 Mar 2007 11:29:00 GMT</pubDate><guid>http://www.shnenglu.com/dbkong/archive/2007/03/06/19310.html</guid><wfw:comment>http://www.shnenglu.com/dbkong/comments/19310.html</wfw:comment><comments>http://www.shnenglu.com/dbkong/archive/2007/03/06/19310.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/dbkong/comments/commentRss/19310.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/dbkong/services/trackbacks/19310.html</trackback:ping><description><![CDATA[ <p>         在filecM,寚w态方法的每一ơ调用都会进行安全检?而由于fileinfocL一个实例类,因此只需要进行一ơ安全检?如何判断应该使用哪个cd?有个l验法则可以参?如果Ҏ(gu)件进行单ơ操?filecL比较好的选择,而如果要Ҏ(gu)件进行多个操?那么使用fileinfocM有更高的效率?/p> <img src ="http://www.shnenglu.com/dbkong/aggbug/19310.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/dbkong/" target="_blank">q_的天?/a> 2007-03-06 19:29 <a href="http://www.shnenglu.com/dbkong/archive/2007/03/06/19310.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.gp402.cn" target="_blank">Ʒһþ㽶߿</a>| <a href="http://www.pudlv.cn" target="_blank">ھƷ99þ</a>| <a href="http://www.naturepro.cn" target="_blank">ԻԻ˿þþ</a>| <a href="http://www.xahjqc.cn" target="_blank">˾Ʒþۺ</a>| <a href="http://www.bjnyjdxcj.cn" target="_blank">ɫۺϾþþþþþþ</a>| <a href="http://www.jinshengsuliao.cn" target="_blank">91Ʒ91þۺ</a>| <a href="http://www.wushuichulisb.cn" target="_blank">þҹҹ³³ƬӰ </a>| <a href="http://www.594n.cn" target="_blank">þۺϾƷþ</a>| <a href="http://www.6kk.org.cn" target="_blank">˾ҹվھƷþþþþþþ</a>| <a href="http://www.abcvi.cn" target="_blank">ƷҹþøƬ</a>| <a href="http://www.9lang.cn" target="_blank">þùAV䡪ٶ</a>| <a href="http://www.yonganwl.cn" target="_blank">9191ƷѾþ</a>| <a href="http://www.hx0451.cn" target="_blank">Ʒþþþþһ </a>| <a href="http://www.bodymaker.com.cn" target="_blank">þˬˬˬ˾þþ</a>| <a href="http://www.lhjban.cn" target="_blank">þþù׮</a>| <a href="http://www.czyhfzc.cn" target="_blank">һɫþۺ޾Ʒ</a>| <a href="http://www.7788mm.cn" target="_blank">þseƷһƷ</a>| <a href="http://www.clkj168.cn" target="_blank">þþƷۺɫ</a>| <a href="http://www.u33w.cn" target="_blank">2021ƷۺϾþ</a>| <a href="http://www.vtkh.cn" target="_blank">2022Ʒþþþ</a>| <a href="http://www.kuaixiansou.cn" target="_blank">þùѾƷ</a>| <a href="http://www.drlf.net.cn" target="_blank">69Ʒþþþվ</a>| <a href="http://www.ht228.cn" target="_blank">˾þav</a>| <a href="http://www.leyuzhe.cn" target="_blank">Ʒþþþþ³</a>| <a href="http://www.lskcop.cn" target="_blank">þùŮѹۿƷ </a>| <a href="http://www.xwbu.cn" target="_blank">þþƷaĻ</a>| <a href="http://www.qh298.cn" target="_blank">ģ˽ĹƷþ</a>| <a href="http://www.52chaoyang.cn" target="_blank">þþûɫƬ</a>| <a href="http://www.handyx.cn" target="_blank">þþþþþþþþþĻ </a>| <a href="http://www.bbcjk.cn" target="_blank">þþƷþ˼˼ </a>| <a href="http://www.41422.com.cn" target="_blank">þþƷwwwˬ</a>| <a href="http://www.gzxwlt.cn" target="_blank">þAVӰ</a>| <a href="http://www.ebankon.com.cn" target="_blank">þҹɫƷAV</a>| <a href="http://www.marsit.cn" target="_blank">޹ƷþõӰŷ</a>| <a href="http://www.seomajor.cn" target="_blank">þþƷƷʢۿ</a>| <a href="http://www.douyinyutang.cn" target="_blank">þҹ1000ϼ</a>| <a href="http://www.rongchenjiaxiao.cn" target="_blank">ձþĻ</a>| <a href="http://www.ahlmnet.cn" target="_blank">޾þһح </a>| <a href="http://www.jianhua365.cn" target="_blank">þþþþþþ˳</a>| <a href="http://www.foundxy.cn" target="_blank">þþþþùƷ </a>| <a href="http://www.puruimu.cn" target="_blank">߳߳þþ91 </a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>