×÷ÕߣºArman Z. Sahakyan¡¡À´Ô´£º²©¿ÍÔ° ¡¡ ¿áÇÚÍøÊÕ¼¯¡¡2008-06-27
¼ò½é
±¾ÎÄ̽ÌÖ»ù±¾µÄͬ²½¸ÅÄ²¢Êµ¼Ê¶¯ÊÖ°ïÖúÐÂÊÖÕÆÎÕ¶àÏ̱߳à³Ì¡£±¾ÎĵÄÖØµãÔÚ¸÷ÖÖͬ²½¼¼ÇÉ¡£
»ù±¾¸ÅÄî
ÔÚÏß³ÌÖ´Ðйý³ÌÖУ¬»ò¶à»òÉÙ¶¼ÐèÒª±Ë´Ë½»»¥£¬ÕâÖÖ½»»¥ÐÐΪÓжàÖÖÐÎʽºÍÀàÐÍ¡£ÀýÈ磬һ¸öÏß³ÌÔÚÖ´ÐÐÍêËü±»¸³ÓèµÄÈÎÎñºó£¬Í¨ÖªÁíÒ»¸öÏß³ÌÈÎÎñÒѾÍê³É¡£È»ºóµÚ¶þ¸öÏß³Ì×ö¿ªÊ¼Ê£ÏµĹ¤×÷¡£
ÏÂÊö¶ÔÏóÊÇÓÃÀ´Ö§³Öͬ²½µÄ£º
1)ÐźÅÁ¿
2)»¥³âËø
3)¹Ø¼üÇøÓò
4)ʼþ
ÿ¸ö¶ÔÏó¶¼Óв»Í¬µÄÄ¿µÄºÍÓÃ;£¬µ«»ù±¾Ä¿µÄ¶¼ÊÇÖ§³Öͬ²½¡£µ±È»»¹ÓÐÆäËû¿ÉÒÔÓÃÀ´Í¬²½µÄ¶ÔÏ󣬱ÈÈç½ø³ÌºÍÏ̶߳ÔÏ󡣺óÁ½ÕßµÄʹÓÃÓɳÌÐòÔ±¾ö¶¨£¬±ÈÈç˵ÅжÏÒ»¸ö¸ø¶¨½ø³Ì»òÏß³ÌÊÇ·ñÖ´ÐÐÍê±ÏΪÁËʹÓýø³ÌºÍÏ̶߳ÔÏóÀ´½øÐÐͬ²½£¬ÎÒÃÇÒ»°ãʹÓÃWait*º¯Êý£¬ÔÚʹÓÃÕâЩº¯Êýʱ£¬ÄãÓ¦µ±ÖªµÀÒ»¸ö¸ÅÄÈκα»×÷Ϊͬ²½¶ÔÏóµÄÄں˶ÔÏ󣨹ؼüÇøÓò³ýÍ⣩¶¼´¦ÓÚÁ½ÖÖ״̬֮һ£ºÍ¨Öª×´Ì¬ºÍδ֪ͨ״̬¡£ÀýÈ磬½ø³ÌºÍÏ̶߳ÔÏ󣬵±ËûÃÇ¿ªÊ¼Ö´ÐÐʱ´¦ÓÚδ֪ͨ״̬£¬¶øµ±ËûÃÇÖ´ÐÐÍê±Ïʱ´¦ÓÚ֪ͨ״̬£¬
ΪÁËÅжÏÒ»¸ö¸ø¶¨½ø³Ì»òÏß³ÌÊÇ·ñÒѾ½áÊø£¬ÎÒÃDZØÐëÅжϱíʾÆäµÄ¶ÔÏóÊÇ·ñ´¦ÓÚ֪ͨ״̬£¬¶øÒª´ïµ½ÕâÑùµÄÄ¿µÄ£¬ÎÒÃÇÐèҪʹÓÃWait*º¯Êý¡£
Wait*º¯Êý
ÏÂÃæÊÇ×î¼òµ¥µÄWait*º¯Êý£º
// create an auto-reset event
CEvent g_eventStart;
UINT ThreadProc1(LPVOID pParam)

{
::WaitForSingleObject(g_eventStart, INFINITE);

return 0;
}
UINT ThreadProc2(LPVOID pParam)

{
::WaitForSingleObject(g_eventStart, INFINITE);

return 0;
}
ÏÂÃæÀ´¿´µÚ¶þ¸öÀý×Ó:
// create a manual-reset event
CEvent g_eventStart(FALSE, TRUE);
UINT ThreadProc1(LPVOID pParam)

{
::WaitForSingleObject(g_eventStart, INFINITE);

return 0;
}
UINT ThreadProc2(LPVOID pParam)

{
::WaitForSingleObject(g_eventStart, INFINITE);

return 0;
}
³ý´ËÒÔÍâʼþ¶ÔÏó»¹ÓÐÒ»¸ö·½·¨£ºCEvent::PulseEvent¡£Õâ¸ö·½·¨Ê×ÏÈʹµÃʼþ¶ÔÏó½øÈëÒÑ֪ͨ״̬£¬È»ºóʹÆäÍ˻ص½Î´Í¨Öª×´Ì¬¡£ÈôʼþÊÇÊÖ¶¯ÖØÖÃÐÍ£¬Ê¼þ½øÈëÒÑ֪ͨ״̬»áÈÃËùÓÐÕýÔڵȴýµÄÏ̵߳õ½Í¨Öª£¬È»ºóʼþ½øÈëδ֪ͨ״̬¡£ÈôʼþÊÇ×Ô¶¯ÖØÖÃÐÍ£¬Ê¼þ½øÈëÒÑ֪ͨ״̬ʱֻ»áÈÃËùÓеȴýµÄÏß³ÌÖ®Ò»µÃµ½Í¨Öª¡£ÈôûÓÐÏß³ÌÔڵȴý£¬Ôòµ÷ÓÃResetEventʲôҲ²»¸É¡£
ʵÀý---¹¤×÷ÕßÏß³Ì
±¾ÎÄËù´øµÄÀý×ÓÖУ¬×÷Õß½«Õ¹Ê¾ÈçºÎ´´½¨¹¤×÷ÕßÏß³ÌÒÔ¼°ÈçºÎºÏÀíµØÏú»ÙËüÃÇ¡£×÷Õß¶¨ÒåÁËÒ»¸ö±»ËùÓÐÏß³ÌʹÓõĿØÖƺ¯Êý¡£µ±µã»÷ÊÓÍ¼ÇøÓòʱ£¬¾Í´´½¨Ò»¸öÏ̡߳£ËùÓб»´´½¨µÄÏß³ÌʹÓÃÉÏÊö¿ØÖƺ¯ÊýÔÚÊÓͼ¿Í»§Çø»æÖÆÒ»¸öÔ˶¯µÄÔ²ÐΡ£ÕâÀï×÷ÕßʹÓÃÁËÒ»¸öÊÖ¶¯ÖØÖÃÐÍʼþ£¬Ëü±»ÓÃÀ´Í¨ÖªËùÓй¤×÷Ïß³ÌÆä“ËÀѶ”¡£³ý´ËÒÔÍ⣬ÎÒÃǽ«¿´µ½ÈçºÎʹµÃÖ÷Ï̵߳ȴýÖ±µ½ËùÓй¤×÷ÕßÏß³ÌÏú»Ùµô¡£
×÷Õß½«Ï̺߳¯Êý¶¨ÒåΪȫ¾ÖµÄ:
struct THREADINFO

{
HWND hWnd;//Ö÷ÊÓÍ¼Çø
POINT point;//Æðʼµã
};
UINT ThreadDraw(PVOID pParam);
extern CEvent g_eventEnd;
UINT ThreadDraw(PVOID pParam)

{
static int snCount = 0;//Ï̼߳ÆÊýÆ÷
snCount ++;//¼ÆÊýÆ÷µÝÔö
TRACE(TEXT("- ThreadDraw %d: started
\n"), snCount);
//È¡³ö´«ÈëµÄ²ÎÊý
THREADINFO *pInfo = reinterpret_cast<THREADINFO *> (pParam);
CWnd *pWnd = CWnd::FromHandle(pInfo->hWnd);//Ö÷ÊÓÍ¼Çø
CClientDC dc(pWnd);
int x = pInfo->point.x;
int y = pInfo->point.y;
srand((UINT)time(NULL));
CRect rectEllipse(x - 25, y - 25, x + 25, y + 25);
CSize sizeOffset(1, 1);
//Ë¢×ÓÑÕÉ«Ëæ»ú
CBrush brush(RGB(rand()% 256, rand()% 256, rand()% 256));
CBrush *pOld = dc.SelectObject(&brush);
while (WAIT_TIMEOUT == ::WaitForSingleObject(g_eventEnd, 0))
{//Ö»ÒªÖ÷Ï̻߳¹Î´Í¨ÖªÎÒ×Ôɱ£¬¼ÌÐø¹¤×÷!(×¢Òâʱ¼äÉèÖÃΪ)
CRect rectClient;
pWnd->GetClientRect(rectClient);
if (rectEllipse.left < rectClient.left || rectEllipse.right > rectClient.right)
sizeOffset.cx *= -1;
if (rectEllipse.top < rectClient.top || rectEllipse.bottom > rectClient.bottom)
sizeOffset.cy *= -1;
dc.FillRect(rectEllipse, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
rectEllipse.OffsetRect(sizeOffset);
dc.Ellipse(rectEllipse);
Sleep(25);//ÐÝÃßÏ£¬¸øÆäËû»æÖÆ×ÓÏß³ÌÔËÐеĻú»á
}
dc.SelectObject(pOld); 
delete pInfo;//ɾ³ý²ÎÊý£¬·ÀÖ¹ÄÚ´æÐ¹Â¶
TRACE(TEXT("- ThreadDraw %d: exiting.\n"), snCount --);//¹é»¹¼ÆÊýÆ÷
return 0;
}
CArray<CWinThread *, CWinThread *> m_ThreadArray;//±£´æCWinThread¶ÔÏóÖ¸Õë

// manual-reset event
CEvent g_eventEnd(FALSE, TRUE);
void CWorkerThreadsView::OnLButtonDown(UINT nFlags, CPoint point)

{
THREADINFO *pInfo = new THREADINFO;//Ï̲߳ÎÊý
pInfo->hWnd = GetSafeHwnd();//ÊÓͼ´°¿Ú
pInfo->point = point;//µ±Ç°µã
//½«½çÃæ×÷Ϊ²ÎÊý´«ÈëÏß³ÌÖУ¬¾Í¿ÉÒÔÔÚÏß³ÌÖÐ×Ô¼º¸üÐÂÖ÷½çÃæ,¶ø²»ÓÃȥ֪ͨÖ÷Ï̸߳üнçÃæ
CWinThread *pThread = AfxBeginThread(ThreadDraw, (PVOID) pInfo, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);//´´½¨Ị̈߳¬³õʼ״̬Ϊ¹ÒÆð
pThread->m_bAutoDelete = FALSE;//Ïß³ÌÖ´ÐÐÍê±Ïºó²»×Ô¶¯Ïú»Ù
pThread->ResumeThread();//Ï߳̿ªÊ¼Ö´ÐÐ
m_ThreadArray.Add(pThread);//±£´æ´´½¨µÄÏß³Ì
}
void CWorkerThreadsView::OnDestroy()

{
g_eventEnd.SetEvent();

/**//* // µÚÒ»ÖÖ·½Ê½
for (int j = 0; j < m_ThreadArray.GetSize(); j ++)
{
::WaitForSingleObject(m_ThreadArray[j]->m_hThread, INFINITE);
delete m_ThreadArray[j];
}
*/
//µÚ¶þÖÖ·½Ê½
int nSize = m_ThreadArray.GetSize();
HANDLE *p = new HANDLE[nSize];
for (int j = 0; j < nSize; j ++)
{
p[j] = m_ThreadArray[j]->m_hThread;
}
::WaitForMultipleObjects(nSize, p, TRUE, INFINITE);
for (int j = 0; j < nSize; j ++)
{
delete m_ThreadArray[j];
}
delete [] p;
TRACE("- CWorkerThreadsView::OnDestroy: finished!\n");
}
ºÍÆäËûͬ²½¶ÔÏó²»Í¬£¬³ý·ÇÓÐÐèÒªÒÔÍ⣬¹Ø¼üÇøÓò¹¤×÷ÔÚÓû§Ä£Ê½Ï¡£ÈôÒ»¸öÏß³ÌÏëÔËÐÐÒ»¸ö·â×°ÔڹؼüÇøÓòÖеĴúÂ룬ËüÊ×ÏÈ×öÒ»¸öÐýת·âËø£¬È»ºóµÈ´ýÌØ¶¨µÄʱ¼ä£¬Ëü½øÈëÄÚºËģʽȥµÈ´ý¹Ø¼üÇøÓò¡£Êµ¼ÊÉÏ£¬¹Ø¼üÇøÓò³ÖÓÐÒ»¸öÐýת¼ÆÊýÆ÷ºÍÒ»¸öÐźÅÁ¿£¬Ç°ÕßÓÃÓÚÓû§Ä£Ê½µÄµÈ´ý£¬ºóÕßÓÃÓÚÄÚºËģʽµÄµÈ´ý£¨ÐÝÃß̬£©¡£ÔÚWin32APIÖУ¬ÓÐÒ»¸öCRITICAL_SECTION½á¹¹Ìå±íʾ¹Ø¼üÇøÓò¶ÔÏó¡£ÔÚMFCÖУ¬ÓÐÒ»¸öÀàCCriticalSection¡£¹Ø¼üÇøÓòÊÇÕâÑùÒ»¶Î´úÂ룬µ±Ëü±»Ò»¸öÏß³ÌÖ´ÐÐʱ£¬±ØÐëÈ·±£²»»á±»ÁíÒ»¸öÏß³ÌÖжϡ£
Ò»¸ö¼òµ¥µÄÀý×ÓÊǶà¸öÏ̹߳²ÓÃÒ»¸öÈ«¾Ö±äÁ¿£º
int g_nVariable = 0;
UINT Thread_First(LPVOID pParam)

{
if (g_nVariable < 100)
{

}
return 0;
}
UINT Thread_Second(LPVOID pParam)

{
g_nVariable += 50;

return 0;
}
Õâ¶Î´úÂë²»ÊÇḬ̈߳²È«µÄ£¬ÒòΪûÓÐÏ̶߳ԱäÁ¿g_nVariableÊǶÀռʹÓõġ£ÎªÁ˽â¾öÕâ¸öÎÊÌ⣬¿ÉÒÔÈçÏÂʹÓãº
CCriticalSection g_cs;
int g_nVariable = 0;
UINT Thread_First(LPVOID pParam)

{
g_cs.Lock();
if (g_nVariable < 100)
{

}
g_cs.Unlock();
return 0;
}
UINT Thread_Second(LPVOID pParam)

{
g_cs.Lock();
g_nVariable += 20;
g_cs.Unlock();

return 0;
}
ÈôÓжà¸ö¹²Ïí×ÊÔ´ÐèÒª±£»¤£¬Ôò×îºÃΪÿ¸ö×ÊԴʹÓÃÒ»¸öµ¥¶ÀµÄ¹Ø¼üÇøÓò¡£¼ÇµÃÒªÅä¶ÔʹÓÃUnLockºÍLock¡£»¹ÓÐÒ»µãÊÇÐèÒª·ÀÖ¹“ËÀËø”¡£
class CSomeClass

{
CCriticalSection m_cs;
int m_nData1;
int m_nData2;
public:
void SetData(int nData1, int nData2)
{
m_cs.Lock();
m_nData1 = Function(nData1);
m_nData2 = Function(nData2);
m_cs.Unlock();
}
int GetResult()
{
m_cs.Lock();
int nResult = Function(m_nData1, m_nData2);
m_cs.Unlock();
return nResult;
}
};
»¥³âËø
ºÍ¹Ø¼üÇøÓòÀàËÆ£¬»¥³âËøÉè¼ÆÎª¶Ôͬ²½·ÃÎʹ²Ïí×ÊÔ´½øÐб£»¤¡£»¥³âËøÔÚÄÚºËÖÐʵÏÖ£¬Òò´ËÐèÒª½øÈëÄÚºËģʽ²Ù×ÝËüÃÇ¡£»¥³âËø²»½öÄÜÔÚ²»Í¬Ïß³ÌÖ®¼ä£¬Ò²¿ÉÒÔÔÚ²»Í¬½ø³ÌÖ®¼ä½ø³Ìͬ²½¡£Òª¿ç½ø³ÌʹÓã¬Ôò»¥³âËøÓ¦¸ÃÊÇÓÐÃûµÄ¡£MFCÖÐʹÓÃCMutexÀàÀ´²Ù×Ý»¥³âËø¡£¿ÉÒÔÈçÏ·½Ê½Ê¹Óãº
ÎÒÃÇ¿ÉÒÔʹÓû¥³âËøÀ´ÏÞÖÆÓ¦ÓóÌÐòµÄÔËÐÐʵÀýΪһ¸ö¡£¿ÉÒÔ½«ÈçÏ´úÂë·ÅÖõ½InitInstanceº¯Êý£¨»òWinMain£©ÖУºÐźÅÁ¿
CSingleLock singleLock(&m_Mutex);
singleLock.Lock(); // try to capture the shared resource
if (singleLock.IsLocked()) // we did it

{
// use the shared resource 
// After we done, let other threads use the resource
singleLock.Unlock();
}
»òÕßͨ¹ýWin32º¯Êý£º
// try to capture the shared resource
::WaitForSingleObject(m_Mutex, INFINITE);
// use the shared resource 


// After we done, let other threads use the resource
::ReleaseMutex(m_Mutex);
HANDLE h = CreateMutex(NULL, FALSE, "MutexUniqueName");
if (GetLastError() == ERROR_ALREADY_EXISTS)

{//»¥³âËøÒѾ´æÔÚ
AfxMessageBox("An instance is already running.");
return(0);
}
ΪÁËÏÞÖÆÊ¹Óù²Ïí×ÊÔ´µÄÏß³ÌÊýÄ¿£¬ÎÒÃÇÓ¦¸ÃʹÓÃÐźÅÁ¿¡£ÐźÅÁ¿ÊÇÒ»¸öÄں˶ÔÏó¡£Ëü´æ´¢ÁËÒ»¸ö¼ÆÊýÆ÷±äÁ¿À´¸ú×ÙʹÓù²Ïí×ÊÔ´µÄÏß³ÌÊýÄ¿¡£ÀýÈ磬ÏÂÃæ´úÂëʹÓÃCSemaphoreÀà´´½¨ÁËÒ»¸öÐźÅÁ¿¶ÔÏó£¬ËüÈ·±£ÔÚ¸ø¶¨µÄʱ¼ä¼ä¸ôÄÚ£¨Óɹ¹Ô캯ÊýµÚÒ»¸ö²ÎÊýÖ¸¶¨£©×î¶àÖ»ÓÐ5¸öÏß³ÌÄÜʹÓù²Ïí×ÊÔ´¡£»¹¼Ù¶¨³õʼʱûÓÐÏ̻߳ñµÃ×ÊÔ´£ºÒ»µ©Ï̷߳ÃÎʹ²Ïí×ÊÔ´£¬ÐźÅÁ¿µÄ¼ÆÊýÆ÷¾Í¼õ1.Èô±äΪ0£¬Ôò½ÓÏÂÀ´¶Ô×ÊÔ´µÄ·ÃÎʻᱻ¾Ü¾ø£¬Ö±µ½ÓÐÒ»¸ö³ÖÓÐ×ÊÔ´µÄÏß³ÌÀ뿪£¨Ò²¾ÍÊÇ˵ÊÍ·ÅÁËÐźÅÁ¿£©¡£ÎÒÃÇ¿ÉÒÔÈçÏÂʹÓãº
CSemaphore g_Sem(5, 5);
// Try to use the shared resource
::WaitForSingleObject(g_Sem, INFINITE);
// Now the user's counter of the semaphore has decremented by one
//
Use the shared resource 
// After we done, let other threads use the resource
::ReleaseSemaphore(g_Sem, 1, NULL);
// Now the user's counter of the semaphore has incremented by one
Ö÷´ÓÏß³ÌÖ®¼äµÄͨÐÅ
ÈôÖ÷Ïß³ÌÏë֪ͨ´ÓÏß³ÌһЩ¶¯×÷µÄ·¢Éú£¬Ê¹ÓÃʼþ¶ÔÏóÊǺܷ½±ãµÄ¡£µ«·´¹ýÀ´È´ÊǵÍЧ£¬²»·½±ãµÄ¡£ÒòΪÕâ»áÈÃÖ÷Ïß³ÌÍ£ÏÂÀ´µÈ´ýʼþ£¬½ø¶ø½µµÍÁËÓ¦ÓóÌÐòµÄÏìÓ¦ËÙ¶È¡£×÷ÕßÌá³öµÄ·½·¨ÊÇÈôÓÏ̷߳¢×Ô¶¨ÒåÏûÏ¢¸ø¸¸Ï̡߳£
#define WM_MYMSG WM_USER + 1ÕâÖ»Äܱ£Ö¤´°¿ÚÀàÖÐΨһ£¬µ«ÎªÁËÈ·±£Õû¸öÓ¦ÓóÌÐòÖÐΨһ£¬¸üΪ°²È«µÄ·½Ê½ÊÇ£º
#define WM_MYMSG WM_APP + 1
afx_msg LRESULT OnMyMessage(WPARAM , LPARAM );
LRESULT CMyWnd::OnMyMessage(WPARAM wParam, LPARAM lParam)

{
// A notification got
// Do something 
return 0;
}
BEGIN_MESSAGE_MAP(CMyWnd, CWnd)

ON_MESSAGE(WM_MYMSG, OnMyMessage)
END_MESSAGE_MAP()
UINT ThreadProc(LPVOID pParam)

{
HWND hWnd = (HWND) pParam;

// notify the primary thread's window
::PostMessage(hWnd, WM_MYMSG, 0, 0);
return 0;
}
µ«Õâ¸ö·½·¨ÓиöºÜ´óµÄȱÏÝ--ÄÚ´æÐ¹Â¶£¬×÷ÕßûÓÐÉîÈëÑо¿£¬¿ÉÒԲο¼ÎÒÕâÆªÎÄÕ¡¶Ç³Ì¸Ò»¸öÏß³ÌͨÐÅ´úÂëµÄÄÚ´æÐ¹Â¶¼°½â¾ö·½°¸ ¡·
Download source files - 47.7 KB
ÔÎÄÁ´½Ó£ºSynchronization in Multithreaded Applications with MFC
À´×Ô£º¡¾Òë¡¿ÆÊÎöMFC¶àÏ̳߳ÌÐòµÄͬ²½»úÖÆ
DWORD WaitForSingleObject
(
HANDLE hHandle,
DWORD dwMilliseconds
);
²ÎÊýhHandle±íʾ´ý¼ì²éÆä״̬£¨Í¨Öª»òÕßδ֪ͨ£©µÄ¶ÔÏó£¬dwMilliseconds±íʾµ÷ÓÃÏß³ÌÔÚ±»¼ì²é¶ÔÏó½øÈëÆä֪ͨ״̬ǰӦ¸ÃµÈ´ýµÄʱ¼ä¡£Èô¶ÔÏó´¦ÓÚ֪ͨ״̬»òÖ¸¶¨Ê±¼ä¹ýÈ¥ÁË£¬Õâ¸öº¯Êý·µ»Ø¿ØÖÆÈ¨¸øµ÷ÓÃÏ̡߳£ÈôdwMillisecondsÉèÖÃΪINIFINITE£¨ÖµÎª-1£©£¬Ôòµ÷ÓÃÏ̻߳áÒ»Ö±µÈ´ýÖ±µ½¶ÔÏó״̬±äΪ֪ͨ£¬ÕâÓпÉÄÜʹµÃµ÷ÓÃÏß³ÌÓÀÔ¶µÈ´ýÏÂÈ¥£¬µ¼Ö“¶öËÀ”¡£
ÀýÈ磬¼ì²éÖ¸¶¨Ïß³ÌÊÇ·ñÕýÔÚÖ´ÐÐ, dwMillisecondsÉèÖÃΪ0,ÊÇΪÁËÈõ÷ÓÃÏß³ÌÂíÉÏ·µ»Ø¡£
DWORD dw = WaitForSingleObject(hProcess, 0);
switch (dw)

{
case WAIT_OBJECT_0:
// the process has exited
break;
case WAIT_TIMEOUT:
// the process is still executing
break;
case WAIT_FAILED:
// failure
break;
}
DWORD WaitForMultipleObjects
(
DWORD nCount,
CONST HANDLE *lpHandles,
BOOL fWaitAll,
DWORD dwMilliseconds
);
ÀýÈ磬ÏÂÃæ´úÂëÅжÏÄĸö½ø³Ì»áÏȽáÊø£º
HANDLE h[3];
h[0] = hThread1;
h[1] = hThread2;
h[2] = hThread3;
DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000);//ÈκÎÒ»¸ö½øÈëÒÑ֪ͨ¾Í·µ»Ø
switch (dw)

{
case WAIT_FAILED:
// failure
break;
case WAIT_TIMEOUT:
// no processes exited during 5000ms
break;
case WAIT_OBJECT_0 + 0:
// a process with h[0] descriptor has exited
break;
case WAIT_OBJECT_0 + 1:
// a process with h[1] descriptor has exited
break;
case WAIT_OBJECT_0 + 2:
// a process with h[2] descriptor has exited
break;
}
¾ä±úÊý×éÖÐË÷ÒýºÅΪindexµÄ¶ÔÏó½øÈëÒÑ֪ͨ״̬ʱ£¬º¯Êý·µ»ØWAIT_OBJECT_0 + Ë÷ÒýºÅ¡£ÈôfWaitAllΪTRUE£¬Ôòµ±ËùÓжÔÏó½øÈëÒÑ֪ͨ״̬ʱ£¬º¯Êý·µ»ØWAIT_OBJECT_0¡£
Ò»¸öÏß³ÌÈôµ÷ÓÃÒ»¸öWait*º¯Êý£¬ÔòËü´ÓÓû§Ä£Ê½Çл»ÎªÄÚºËģʽ¡£Õâ´øÀ´µÄºó¹ûÓкÃÓлµ¡£²»ºÃµÄÊÇÇл»½øÈëÄÚºËģʽ´ó¸ÅÐèÒª1000¸öʱÖÓÖÜÆÚ£¬ÕâÏûºÄ²»ËãС¡£ºÃµÄÊǵ±½øÈëÄÚºËģʽºó£¬¾Í²»ÐèҪʹÓô¦ÀíÆ÷£¬¶øÊǽøÈëÐÝÃß̬£¬²»²ÎÓë´¦ÀíÆ÷µÄµ÷¶ÈÁË¡£
ÏÖÔÚÈÃÎÒÃǽøÈëMFC£¬²¢¿´¿´ËüÄÜΪÎÒÃÇ×öЩʲô¡£ÕâÀïÓÐÁ½¸öÀà·â×°Á˶ÔWait*º¯ÊýµÄµ÷ÓÃ: CSingleLockºÍCMultiLock¡£ ͬ²½¶ÔÏó µÈ¼ÛµÄC++Àà
Events
CEvent
Critical sections
CCriticalSection
Mutexes
CMutex
Semaphores
CSemaphore
ÿ¸öÀà¶¼´ÓÒ»¸öÀà--CSyncObject¼Ì³ÐÏÂÀ´£¬´ËÀà×îÓÐÓõijÉÔ±ÊÇÖØÔØµÄHANDLEÔËËã·û£¬Ëü·µ»ØÖ¸¶¨Í¬²½¶ÔÏóµÄÄÚÔÚ¾ä±ú¡£ËùÓÐÕâЩÀà¶¼¶¨ÒåÔÚ<AfxMt.h>Í·ÎļþÖС£
ʼþ
Ò»°ãÀ´Ëµ£¬Ê¼þÓÃÓÚÕâÑùµÄÇéÐÎÏ£ºµ±Ö¸¶¨µÄ¶¯×÷·¢Éúºó£¬Ò»¸öỊ̈߳¨»ò¶à¸öỊ̈߳©²Å¿ªÊ¼Ö´ÐÐÆäÈÎÎñ¡£ÀýÈ磬һ¸öÏ߳̿ÉÄܵȴý±ØÐèµÄÊý¾ÝÊÕ¼¯Íêºó²Å¿ªÊ¼½«Æä±£´æµ½Ó²ÅÌÉÏ¡£ÓÐÁ½ÖÖʼþ£ºÊÖ¶¯ÖØÖÃÐͺÍ×Ô¶¯ÖØÖÃÐÍ¡£Í¨¹ýʹÓÃʼþ£¬ÎÒÃÇ¿ÉÒÔÇáËɵØÍ¨ÖªÁíÒ»¸öÏß³ÌÌØ¶¨µÄ¶¯×÷ÒѾ·¢ÉúÁË¡£¶ÔÓÚÊÖ¶¯ÖØÖÃÐÍʼþ£¬Ïß³ÌʹÓÃËü֪ͨ¶à¸öÏß³ÌÌØ¶¨¶¯×÷ÒѾ·¢Éú£¬¶ø¶ÔÓÚ×Ô¶¯ÖØÖÃÐÍʼþ£¬Ïß³ÌʹÓÃËüÖ»¿ÉÒÔ֪ͨһ¸öÏ̡߳£ÔÚMFCÖУ¬CEventÀà·â×°ÁËʼþ¶ÔÏó£¨ÈôÔÚwin32ÖУ¬ËüÊÇÓÃÒ»¸öHANDLEÀ´±íʾµÄ£©¡£CEventµÄ¹¹Ô캯ÊýÔËÐÐÎÒÃÇÑ¡Ôñ´´½¨ÊÖ¶¯ÖØÖÃÐͺÍ×Ô¶¯ÖØÖÃÐÍʼþ¡£Ä¬ÈϵĴ´½¨ÀàÐÍÊÇ×Ô¶¯ÖØÖÃÐÍʼþ¡£ÎªÁË֪ͨÕýÔڵȴýµÄỊ̈߳¬ÎÒÃÇ¿ÉÒÔµ÷ÓÃCEvent::SetEvent·½·¨£¬Õâ¸ö·½·¨½«»áÈÃʼþ½øÈëÒÑ֪ͨ״̬¡£ÈôʼþÊÇÊÖ¶¯ÖØÖÃÐÍ£¬Ôòʼþ»á±£³ÖÒÑ֪ͨ״̬£¬Ö±µ½¶ÔÓ¦µÄCEvent::ResetEvent±»µ÷Óã¬Õâ¸ö·½·¨½«Ê¹µÃʼþ½øÈëδ֪ͨ״̬¡£Õâ¸öÌØÐÔʹµÃÒ»¸öÏ߳̿ÉÒÔͨ¹ýÒ»¸öSetEventµ÷ÓÃȥ֪ͨ¶à¸öÏ̡߳£ÈôʼþÊÇ×Ô¶¯ÖØÖÃÐÍ£¬ÔòËùÓÐÕýÔڵȴýµÄÏß³ÌÖÐÖ»ÓÐÒ»¸öÏ̻߳á½ÓÊÕµ½Í¨Öª¡£µ±ÄǸöÏ߳̽ÓÊÕµ½Í¨Öªºó£¬Ê¼þ»á×Ô¶¯½øÈëδ֪ͨ״̬¡£
ÏÂÃæÁ½¸öÀý×Ó½«Õ¹Ê¾ÉÏÊöÌØÐÔ£º
·ÖÀࣺ Windows±à³Ì .NET¼¼Êõ ÓÎÏ·¿ª·¢

