      

              
Windows,      
.  , , ,   1    ,   
  Windows    .  
   .       
 Windows.  ,  , ,  
.          
 .      .  
   Win32    Windows 95  
Windows NT.      .  Windows 95/NT  
      ,      ,  
.           
  .      
          
      .    
  MFC    . 

    363 

            
,  .    
  ( )   .  Win32  
   .    ,  MFC 
   . 

    :  Windows 3.1     
 (  )     . 
 ,    ,    Windows 3.1. 


      

           
,      
    .    
  . ,     
      ,     
    ,       
  .       
   ,      
  . 
     ,          
.        .    
        .   , 
   ,     .  , 
     ,     
  .   ,   
   ,  .   
 . 
     MFC    :   .  
     .   MFC, 
    .  ,   
 MFC- (     CWinApp) 
  .        
.        
 .       
   .   ,     
    ,     
  ,     
.         . 

    :  ,    API  ,   
  .       
   MFC. 


    364                                     MFC:   

     MFC       CWinThread, 
 ,      CWinApp,   
 . 
      ,      ,  
      AFXMT.H. 

       

          AfxBeginThread().  
 : 

    CMinThread::AfxBeginThread(AFX_THREADPROC ThreadFunc, 
    LPVOID Param, 
    int InitPriority= 
    THREAD_PRIORITY_NORMAL, 
    DINT StackSize^O, DWORD dwFlags =0, 
    LPSECURITY_ATTRIBUTES Security=NULL) ; 

             
  ,   .   
   ,      .  
  (..    )    ThreadFunc. 
      : 

    UINT ThreadFunc(LPVOID TFParam); 

        AfxBeginThread()   
    TFParam.  32-   
   . 
          InitPriority.   
  ,      .  
         : 

    THREAD_PRIORITY_TIME_CRITICAL 
    THREAD_PRIORITY__HIGHEST 
    THREAD_PRIORITY_ABOVE_NORMAL 
    THREAD_PRIORITY_NORMAL 
    THREAD_PRIORITY_BELOW_NORMAL 
    THREAD_PRIORITY_LOWEST 
    THREAD_PRIORITY_IDLE 

        .       
 StackSiw.     ,    
     ,     , ,  
,     . (   
     .) 
     ^'/'/   .   
  ,     .   
  CREATE_SUSPEND,     , 
..  . (   ,    CWinTliread::ResumeTlireadO.) 

    14.                                         365 

     Security       , 
-1    .     NULL,   
     . 
        AfxBeginThread()    
 ,     .   
 ,      
    .   , , 
         
  .    ,  
,   . 

      

      ,       
.    "  "    
AlxEndThread(),    : 

    void AfxEndThread(UINT Status); 

      Status    .  , 
         . 

       

          - i 
.      Execute Thread   Threads  : 
    .    10  
            
.        .  
        
 ,    8.      
. 14.1. ' 

    . 14.1.     


    366                                          MFC:   

         : 

    tfinclude <afxres.h> 
    Unclude "ids.h" 
    
    ThreadMenu MENU 
    { 
    POPUP "&Threads" { 
    MENUITEM "Execute &Thread\tF2", IDM_THREAD 
    MENUITEM "E&xit\tF3", IDM_EXIT 
    ) 
    MENUITEM "&Help", IDM_HELP 
    ) 
    ThreadMenu ACCELERATORS 
    ( 
    VK_F1, IDM_HELP, VIRTKEY 
    VK_F2, IDM_THREAD, VIRTKEY 
    VK_F3, IDMJ3XIT, VIRTKEY 
    } 
        IDS.H: 
    // THREAD.H 
    ^define IDM_THREAD 100 
    ^define IDM_HELP    101 
    #define IDM_EXIT    102 
       THREAD.H,    : 
    // THREAD.H 
    
    //       
    class CMainWin : public CFrameWnd 
    ( 
    public: 
    int m X, m Y;     //     
    
    CDC m memDC;      //  ,   
    //   
    CBitmap m_bmp;    //    
    CBrush m_bkbrush; //     
    CMainWin() ; 
    afx msq void OnPaintO; 
    afx_msg void OnLButtonDown(UINT Flags, CPoint Loc) ; 
    afx msg void OnThreadO; 
    afx msg void OnExitO; 
    afx msg void OnHelpO; 


    14.                                         367 


    DECLARE_MESSAGE_MAP() }; 
    
    //      
    class CApp : public CMinApp 
    { 
    public: 
    BOOL Initlnstance (); 
    ); 

        : 


    //     
    
    #include <afxwin.h> 
    ^include <string.h> 
    ^include "ids.h" 
    ^include "thread.h" 
    UINT MyThread(LPVOID HinObjPtr); 
    int ThreadID = 0; 
    int maxX, maxY; 
    //     
    CMainWin::CMainWin() 
    { 
    Create(NULL, "Multithreading", 
    WS_OVERLAPPEDWINDOM, rectDefault, 
    NULL, "ThreadMenu"); 
    
    //     
    if(iLoadAccelTable("ThreadMenu")) 
    MessageBox("Cannot Load Accelerators", "Error"); 
    m_X = m_Y = 0; 
    maxX = GetSystemMetrics(SM_CXSCREEN) ; 
    maxY = GetSystemMetrics(SM_CYSCREEN) ; 
    CClientDC DC(this); 
    
    //     
    m_memDC.CreateCompatibleDC(&DC) ; 
    m bmp.CreateCompatibleBitmap(&DC, maxX, maxY) ; 
    m memDC.SelectObject(&m bmp); 
    
    //    
    m_bkbrush.CreateStockObject(MHITE_BRUSH) ; 
    m_memDC.SelectObject(&m_bkbrush) ; 
    
    //     
    m_memDC.PatBlt(0, 0, maxX, maxY, PATCOPY) ; 
    ) 


    368                                     MFC:   


    //   
    BOOL CApp::Initlnstance() 
    ( 
    m pMainWnd = new CMainWin; 
    m pMainWnd->ShowWindow(m nCmdShow); 
    m pMainWnd->UpdateWindow() ; 
    return TRUE; 
    ) 
    
    //     
    BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd) 
    ON_WM_PAINT() 
    ON_WM_LBUTTONDOWN() 
    ON_COMMAND(IDMJTHREAD, OnThread) 
    ON_COMMAND(IDM_EXIT, OnExit) 
    
    ON_COMMAND(IDM_HELP, OnHelp) 
    END_MESSAGE_MAP() 
    //       
    afx msg void CMainWin::OnPaint() 
    ( 
    CPaintDC DC(this) ; 
    DC.BitBltfO, 0, maxX, maxY, &m_memDC, , , SRCCOPY); 
    ) 
    //      
    //      
    afx_msq void CMainWin::OnLButtonDown(UINT Flags, CPoint Loc) 
    { 
    m X = Loc.x; 
    m Y = Loc.y; 
    } 
    
    //   IDM_EXIT 
    afx msg void CMainWin::OnExit() f 
    int response; 
    response = MessageBox("Quit the Program?", "Exit", MB_YESNO) ; 
    if (response == IDYES) 
    SendMessage(WM CLOSE); //   
    ) 
    
    //   IDM HELP 
    afx msg void CMainWin::OnHelp() 1 
    MessageBox("Multithreading", "Help"); 
    ) 
    
    //   IDM^THREAD 
    afx msg void CMainWin::OnThread() 


    14.                                         369 


    AfxBeg:i-nThread(MyThread, this);                                    f 
    
    //                                                       
    UINT MyThread(LPVOID WinObjPtr)                                     | 
    { 
    int i; 
    TEXTMETRIC tm; 
    int Tid = ThreadID; 
    char str[255] ; 
    ThreadID++; 
    CMainMin *ptr = (CMainWin *) WinObjPtr; 
    
    //    
    ptr->m_memDC.GetTextMetrics(&tm) ; 
    
    for(i=0; i<10; i++) ( 
    Sleep(500) ; 
    
    wsprintf (str, "Thread #%d, beep #%d", Tid, i);                . 
    ptr->m_memDC.TextOut(ptr->m_X, ptr->m_Y, str, strlen (str)); 
    ptr->m Y = ptr->m Y + tm.tmHeight + tm.tmExternalLeading; 
    ptr->InvalidateRect(NULL) ; 
    MessageBeep(MB_OK) ; 
    ) 
    ThreadID--; 
    return 0; 
    } 
    CApp App; //    

               
  MyThreadQ.      
    CMainWin, ,  ,    
 . 
       ThreadID     MyThreadQ, 
    .     
       .    
    .      . 
     ,      MyThreadQ   
Sleep().  API-       
  .     MyThread() ; 
 ,      "" 
.        API-, MessageBeepQ, 
   . 
      MyThreadO      
 ,     . , 
,   :    Threads  
Execute Thread,  ,    ,     
.  | 

    370                                    MFC:   

    ,         
   . 

       

         ,  .   
          Execute 
Thread.       . 14.2.   
    ,    
   . 

    //     
    #include <afxwin.h> 
    #include <string.h> 
    #include "ids.h" 
    ^include "thread.h" 
    UINT MyThreadI(LPVOID WinObjPtr); 
    UINT MyThread2(LPVOID WinObjPtr); 
    int FirstThreadID = 0; 
    int SecondThreadID = 0; 
    jnt maxX, maxY; 
    //     
    CMainWin::CMainWin() 
    ( 
    Create(NULL, "Multithreading", 
    WS_OVERLAPPEDWINDOW, rectDefault, 
    NULL, "ThreadMenu"); 
    
    //     
    if('LoadAccelTable("ThreadMenu")) 
    MessageBox("Cannot Load Accelerators", "Error"); 
    m_X = m_Y- = 0; 
    maxX = GetSystemMetrics(SM_CXSCREEN); 
    maxY = GetSystemMetrics(SM_CYSCREEN) ; 
    CCiientDC DC(this) ; 
    
    //     
    m_memDC.CreateCompatibleDC(&DC) ; 
    m bmp.CreateCompatibleBitmap(&DC, maxX, maxY); 
    m memDC.SelectObject(&m_bmp); 
    
    //    
    m_bkbrush.CreateStockObj ect(WHITE_BRUSH) ; 


    14.                                         371 


     
    m_memDC.SelectObject(&m_bkbrush) ; 
    
    //     
    m_memDC.PatBlt(0, 0, maxX, maxY, PATCOPY); 
    } 
    
    //   
    BOOL CApp::Initlnstance () 
    ( 
    iT]_pMainMnd = new CMainWin; 
    m_pMainWnd->ShowMindow(m nCmdShow) ; 
    rn__pMainHnd->UpdateWindow() ; 
    return TRUE; 
    ) 
    
    //     
    BEGIN_MESSAGE_MAP(CMainMin, CFrameWnd) 
    ON_WM_PAINT () 
    ON_WM_LBUTTONDOWN() 
    ON_COMMAND(IDM_THREAD, OnThread) 
    ON_COMMAND(IDM_EXIT, OnExit) 
    
    ON_COMMAND(IDM_HELP, OnHelp) 
    END_MESSAGE_MAP() 
    //       
    afx_msq void CMainWin::OnPaint() 
    ( 
    CPaintDC DC (this) ; 
    DC.BitBlt(0, 0, maxX, maxY, Sm_memDC, , , SRCCOPY) ; 
    1 
    //      
    //      
    afx_msq void CMainWin::OnLButtonDown(UINT Flags, CPoint Loc)         ! 
    1 
    m X = Loc.x; 
    m Y = Loc.y; 
    } 
    
    //   IDM_EXIT 
    afx msg void CMainWin::OnExit() 
    ( 
    int response; 
    response = MessageBox("Quit the Program?", "Exit", MB_YESNO) ; 
    if(response == IDYES) 
    SendMessage(HM CLOSE); //   
    } 
    //   IDM HELP 


    372                                     MFC:   


    afx_msg void CMainWin::OnHelp() 
    ( 
    MessageBox("Multithreading", "Help") ; 
    1 
    
    //   IDM THREAD 
    afx msg void CMainWin::OnThread() 
    ( 
    //     
    AfxBeginThread(MyThreadI, this) ; 
    AfxBeginThread(MyThread2, this) ; 
    ) 
    //    
    HINT MyThreadI(LPVOID WinObjPtr) 
    f 
    int i; 
    TEXTMETRIC tm; 
    char str[255] ; 
    int Tid = FirstThreadID; 
    FirstThreadID++; 
    CMainWin *ptr = (CMainWin *) WinObjPtr; 
    
    //    
    ptr->m_memDC.GetTextMetrics(Stm) ; 
    
    for(i=0; i<10; i++) { 
    Sleep (500) ; 
    wsprintf (str, "First Thread #od, beep #%d", Tid, i); 
    ptr->m_memDC.TextOut(ptr->m_X, ptr->m_Y, str, strlen (str)) ; 
    ptr->m_Y = ptr->m_Y + tm.tniHeight + tm.tmExternalLeading; 
    ptr->InvalidateRect(NULL) ; 
    MessageBeep(MB_OK) ; 
    } 
    FirstThreadID--; 
    return 0; 
    
    //    
    HINT MyThread2(LPVOID WinObjPtr) 
    int i; 
    TEXTMETRIC tm; 
    char str[255] ; 
    int Tid = SecondThreadID; 
    SecondThreadID++; 
    CMainWin *ptr = (CMainWin *) WinObjPtr; 


    14.                                         373 


    //    
    ptr->m_memDC.GetTextMetrics(&tm) ; 
    
    for(i=0; i<10; i++) { 
    Sleep (200) ; 
    wsprintf (str, "Second Thread #%d, beep #%d", Tid, i); 
    ptr->m_memDC.TextOut(ptr->m X, ptr->m Y, str, strlen (str)) ; 
    ptr->m_Y = ptr->m_Y + tm.tmHeight + tm.tmExternalLeading; 
    ptr->InvalidateRect(NULL) ; 
    MessageBeep(MB_OK) ; 
    } 
    SecondThreadID--; 
    return 0; 
    } 
    CApp App; //    


    . 14.2.      

        ,       
             
  .      
.       , 
  . 

    374                                    MFC:   


         

           SuspendThread().  
    .    
    ResumeThread().    : 

    DWORD CWinThread::SuspendThread() ; 
    DWORD CWinThread::ResumeThread() ; 

           .    
 ,    .    
     .     
SuspendThread()      . , 
,     ResunieThread()    
  .       
 ,     .  ,  
   ResumeThread()      SuspendThread(). 
            
  -1,   . 

       

          .   
    :     
        . 
 ,        
      .   
,      .    
    ,       
  . ,  ,     
,         
   ,     . 
            
GetPriorityClassQ,         
SetPriorityClass().    API-      
CWinThread.    : 

    DWORD GetPriorityClass(HANDLE hApp); 
    BOOL SetPriorityClass(HANDLE hApp, DWORD dwPrlority); 

      hApp   .  
GetPriorityClass()     .   
SetPriorityClass()  civ/Priority    .  
 ,      : 

    REALTIME_PRIORITY_CLASS 
    HIGH_PRIORITY_CLASS 
    NORMAL_PRIORITY_CLASS 
    IDLE_PRIORITY_CLASS 


    14.                                         375 

         NORMAL_PRIORITY_CLASS.  
,    . ,    
       . 
,       
REALTIME_PRIORITY_CLASS     .   
       
,      .     
   ,    . 
      (   )   ,  
       .   
    .      
     . 
       -  CWinThread. 
        
GetThreadPriorityO         
 SetThreadPriority().    : 

    BOOL CHinThread::SetThreadPriority(int Priority); 
    int CWinThread::GetThreadPriority () ; 

      SetThreadPriorityO  Priority    
.   GetThreadPriorityO   .  
 ,      : 

    THREAD_PRIORITY_TIME_CRITICAL 
    THREAD_PRIORITY_HIGHEST 
    THREAD_PRIORITY_ABOVE_NORMAL 
    THREAD_PRIORITY_NORMAL 
    THREAD_PRIORITY_BELOH_NORMAL 
    THREAD_PR IORITY_LOWEST 
    THREAD_PRIORITY_IDLE 

            
  Win32  31   .   
      ,   
   . 

     

    ,       ,  
       .   
    ,         
  *,        
 . ,       , 
       . , 
 ,   .    
    ,  
    *     ,      
   .  . . 

    376                                     MFC:   

       ,   . , 
  - ,       
   .       . 
       ,     . -, 
   (    ,    
   ). -,    .  
       ,    
       . 
             ,  
    (),       
    .      , 
   . 

       

     Windows   ,    
     ,     
        ,    
   .   , ,    
    ,     
.  ,       
 ,   ,      
  R (   ).     
        .  
       R   ,    
  ,     . -, 
   nag,      . 
    . -,     
 ,       R,   
 4) (..  ,   ),   
 (  flag  ),    R  
      .  ,     R 
      : 

    while(flag); // ,     
    :lag = 1; //   
    / ...    R ... 
    flag = 0; //   

         ,       
   R   ,   flag    . 
,       .  
,        !  
,   . 
      ,        
     R.  ,   while  

    14.                                         377 

        flag  .  , 
-^   .   ,     
    .    ,   
  - |     .   
  - j  flag     
,          
R. ,       while ,  
 flag  ,      R.    
,    flag    ,  
,   ,     .  
   while,   ,   flag  
,   R .       
      !     ,  
     flag     
.   ,       
 .      ,    
     R      
   . 
         ,    , 
.   (   Windows)  , 
       ,   . 
    .     
       .  
 ,  ,      
   ,  .  Win32 API 
      . , 
  MFC     . 

      

     Win32     .  . 
  ,    .     
 ,   () .   
        .  
       (      
        ),  
        . 4 
   ,   ,   
 ,  ,    . 
           (mutex 
semaphore).        ,   
           . 
,     . 
         ,    
(event object).          , 
 -        ,    
  .  ,     
  . 

    378                                     MFC:   

     ,        
  .       
    (critical section).      
 ,          ,  
      . (   
    .) 
       ,     
         
. ,      
  . 
       ,      
  .    ,    
      . 

       MFC 

     MFC  ,   Win32, 
     (. 14.1): 

     14.1.   

                        

    CCriticalSection          
    CEvent                 
    CMutex                 
    CSemaphore             

         CSyncObject,    
 ,     . 
     MFC      : 
CSingleLock  CMultiLock.        
 -,       
.  CSingleLock      , 
  CMultiLock    .    
   CSingleLock. 

     CSingleLock 

       ,       
  CSingleLock.        
CSingleLock    : 

    CSingleLock (CSyncObject *SyncOb, BOOL Jn-lt.ia-;State=FALSE) ; 

      SyncOb     , 
 .   InilialState ,   
      .     
 ,    .      
  . 

    14.                                         379 

       CSingleLock ,   ,   
  SyncOb,      : 
Lock() i Unlock().   : 

    BOOL CSingleLock: : Lock (DWORD dwOe-Iay=INFINITE) ; 
    BOOL CSingleLock::Unlock (); 
    BOOL CSingleLock: :Unlock (LONG Count, LONG * Previous=WL~L} ; 

     Lock()       
.        
.   civ/Delay ,     
     .    , 
 .     ,    
INFINITE.        (.. 
  )  ,   .     
  Lock()  ,    
,   . 
     Unlock()   ,    
    .     
 ,    ,   .  
   Count ,       
.        , 
     .  Previous 
  ,       
.     ,    NULL.   
          
   . 
        CSingleLock      
 : 
    1.    CSyncObject ( ),   
     . 
    2.    ,    ,  
  CSingleLock. 
    3.        Lock(). 
    4.    . 
    5.   UnlockQ,   . 
        ,        
    . 
    :   , CSyncObject,   
 Lock()  Unlock(),       
    ( )    
 CSingleLock  CMultiLock.   Microsoft  - 
   CSingleLock  CMultiLock.       
  . 

    380                                    MFC:   


       

       ,      
 .        
  CSemaphore.      : 

    CSemaphore(LONG InitialCount=\, 
    LONG MaxCount=l, 
    LPSTR lpszName=mLL, 
    LPSECURITY_ATTRIBUTES Securi?y=NULL) ; 

             . 
  ,     , 
   MaxCount.     ,   
 , ..        
  . 
      ,   ,    
    .     ,  
       ,      
 .       
 InitialCount.    ,   ,  , 
 ,     -  . , 
,    ,  , ,    
    .   InituilCounl   
      MaxCount. 
     Ips^Name   ,    . 
        
 .  ,       
 ,         . 
   .      
NULL.          . 
     Security       , 
  .     NULL,    
     . 

        

          .  
    ,        
    .       . 
 ,   Sema    CMainWin.  
    . 14.3. 

    14.                                         381 


    . 14.3.     

              IDS.H, 
    .     SEMA.H,  
  : 

    //  SEMA.H 
    //       
    class CMainWin : public CFrameMnd 
    ( 
    public: 
    int m X, m Y; //     
    
    CDC m memDC; //  ,   
    //   
    CBitmap m bmp; //    
    CBrush m bkbrush; //     
    
    CSemaphore Sema; //   
    CMainWin() ; 
    afx msg void OnPaintO; 
    afx_msg void OnLButtonDown(UINT Flags, CPoint Loc) ; 
    afx msg void OnThreadO; 
    afx msg void OnExitO; 
    afx_msg void OnHelpO; 


    382                                     MFC:   


    DECLARE_MESSAGE_MAP() 
    //      
    class CApp : public CWinApp 
    ( 
    public: 
    BOOL Initlnstance (); 
    
       : 
    //   
    
    Tinclude <afxwin.h> 
    ^include <afxmt.h> 
    ^include <string.h> 
    ^include "ids.h" 
    ttinclude "sema.h" 
    UINT MyThreadI(LPVOID WinObjPtr); 
    UINT MyThread2(LPVOID WinObjPtr); 
    int FirstThreadID = 0; 
    int SecondThreadID = 0; 
    int maxX, maxY; 
    //     
    CMainWin::CMainWin() 
    ( 
    Create (NULL, "Using a Semaphore", 
    WS__OVERLAPPEDWINDOW, rectDefault, 
    NULL, "ThreadMenu"); 
    
    //     
    if('LoadAccelTable("ThreadMenu")) 
    MessageBox ("Cannot Load Accelerators", "Error"); 
    m_X = m_Y = 0; 
    maxX = GetSystemMetrics(SM_CXSCREEN) ; 
    maxY = GetSystemMetrics(SM_CYSCREEN) ; 
    CClientDC DC(this); 
    
    //     
    m_memDC.CreateCompatibleDC(&DC) ; 
    m bmp.CreateCompatibleBitmap(&DC, maxX, maxY) ; 
    m memDC.SelectObject(&m bmp); 
    
    //    
    m_bkbrush.CreateStockObject(WHITE_BRUSH) ; 


    74.                                         383 


    m memDC.SelectObject(&m bkbrush);                                
    I /                                  i 
    m_memDC.PatBlt(0, 0, maxX, maxY, PATCOPY); 
    } 
    
    //   
    BOOL CApp::Initlnstance () 
    { 
    m_pMainWnd = new CMainWin; 
    m_pMainWnd->ShowWindow(m_nCmdShow) ; 
    m pMainWnd->UpdateWindow(); 
    return TRUE; 
    } 
    
    //     
    BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd) 
    ON_WM_PAINT() 
    ON_WM_LBUTTONDOWN() 
    ON_COMMAND(IDM_THREAD, OnThread) 
    ON_COMMAND(IDM_EXIT, OnExit) 
    ON_COMMAND(IDM_HELP, OnHelp) 
    END_MESSAGE_MAP() 
    //       
    afx_msg void CMainWin::OnPaint() 
    { 
    CPaintDC DC(this);                                                 ,, 
    DC.BitBlt(0, 0, maxX, maxY, &m_memDC, , , SRCCOPY) ; 
    ) 
    //      
    //      
    afx msq void CMainWin::OnLButtonDown(UINT Flags, CPoint Loc) 
    ( 
    m_X = Loc.x; 
    m Y = Loc.y; 
    ) 
    
    //   IDM_EXIT 
    afx msg void CMainWin::OnExit () 
    { 
    int response; 
    response = MessageBox ("Quit the Program?", "Exit", MB_YESNO) ; 
    if(response == IDYES) 
    SendMessage(WM CLOSE); //   
    ) 
    //   IDM_HELP 


    384                                     MFC:   


    afx msg void CMainWin::OnHelp () 
    ( 
    MessageBox("Semaphore", "Help"); 
    ) 
    
    //   IDM THREAD 
    afx msg void CMainWin::OnThread() 1 
    AfxBeginThread(MyThreadI, this) ; 
    AfxBeginThread(MyThread2, this) ; 
    
    //    
    UINT MyThreadI(LPVOID WinObjPtr) 
    ( 
    int i; 
    TEXTMETRIC tm; 
    char str [255] ; 
    int Tid = FirstThreadID; 
    FirstThreadID++; 
    CMainWin *ptr = (CMainWin *) WinObjPtr; 
    //    
    ptr->m memDC.GetTextMetrics(&tm) ; 
    CSingleLock SyncOb(&(ptr->Sema)) ; 
    SyncOb.Lock (); //   
    
    for(i=0; i<10; i++) ( 
    Sleep (500) ; 
    wsprintf (str, "First Thread #%d, beep #%d", Tid, i); 
    ptr->m_memDC.TextOut(ptr->m_X, ptr->m_Y, str, strlen (str)); 
    ptr->m Y = ptr->m Y + tm.tmHeight + tm.tmExternalLeading; 
    ptr->InvalidateRect(NULL) ; 
    MessageBeep(MB_OK) ; 
    t 
    FirstThreadID--; 
    
    SyncOb.Unlock(); //   
    return 0; 
    //    
    UINT MyThread2(LPVOID WinObjPtr) 
    ( 
    int i; 
    TEXTMETRIC tm; 
    char str[255] ; 
    int Tid = SecondThreadID; 


    14.                                         385 


    SecondThreadID++; 
    CMainWin *ptr = (CMainWin *) WinObjPtr; 
    
    //    
    ptr->m_memDC.GetTextMetrics(&tm) ; 
    CSingleLock SyncOb(&(ptr->Sema)) ; 
    SyncOb.Lock(); //   
    
    for(i=0; i<10; i++) { 
    Sleep (200) ; 
    wsprintf (str, "Second Thread #%d, beep #od", Tid, i); 
    ptr->m_memDC.TextOut(ptr->m_X, ptr->m_Y, str, strlen (str)); 
    ptr->m_Y = ptr->m_Y + tm.tmHeight + tm.tmExternalLeading; 
    ptr->InvalidateRect(NULL) ; 
    MessageBeep(MB_OK); 
    } 
    SecondThreadID--; 
    SyncOb.Unlock(); //   
    return 0; 
    } 
     ; //    

     CMainWin   ,  Sema.  -1 
   MyThreadl()  MyThread2()    
  .        CSingleLock,  
   Lock().       
,      ,     
     Unlock().  ,  
    .     
 .     
     . 

        

      ,       
   ,    .     
   CEvent.      : 

    CEvent (BOOL InitialState=FALS'E, 
    BOOL ManuaJ=FALSE, 
    LPSTR JpszName=NULL, 
    LPSECURITY_ATTRIBUTES Security=NULL) ; 

      InitialStare    . 
   TRUE,     ( ),   FALSE, 

    386                                     MFC:   

          (  ).  
Manual ,         
 .     TRUE ( ),   
       ResetEventQ.    
       
  . 
     IpszName   ,    . 
        
  .  ,     
    ,      
   .     .   
   NULL.         
  . 
     Security       , 
   .     NULL,   
      . 
       ,  ,   ,   
      CSingleLock,     
CSingleLock::Lock().         
,     . 
       ,   ,   
SetEvent(),   : 

    BOOL CEvent::SetEvent(); 

         ,  ,   
  ( CSingleLock: :Lock() )   
 .        
     . 
             
ResetEventQ  ,      .  
  : 

    BOOL CEvent::ResetEvent(); 

          .    
           . 

         

      ,     
   .      MyThreadlQ  
   ,   MyThread2()     
   .  ,   
MyThread2()  ,    MyThreadlQ  
    . 14.4. 

    74.                                         387 


    . 14.4.      

              IDS.H, 
    .     EVENT.H,  
  : 

    //  EVENT.H 
    //       
    class CMainWin : public CFrameWnd 
    ( 
    public: 
    int m X, m Y; //     
    
    CDC m memDC; //  ,   
    //   
    CBitmap m bmp; //    
    CBrush m bkbrush; //     
    
    CEvent Event; //   
    CMainWin() ; 
    afx msg void OnPaintO; 
    afx msg void OnLButtonDown(DINT Flags, CPoint Loc) ; 
    afx msg void OnThreadO; 
    afx msg void OnExitf); 
    afx msg void OnHelpO; 


    388                                    MFC:   


    DECLARE_MESSAGE_MAP() 
    
    //      
    class CApp : public CWinApp 
    ( 
    public: 
    BOOL Initlnstance (); 
       : 
    //    
    
    include <afxwin.h> 
    ^include <afxmt.h> 
    #include <string.h> 
    #include "ids.h" 
    #include "event.h" 
    UINT MyThreadI(LPVOID WinObjPtr); 
    HINT MyThread2(LPVOID WinObjPtr); 
    int FirstThreadID = 0; 
    int SecondThreadID = 0; 
    int maxX, maxY; 
    //     
    CMainWin::CMainWin() 
    f 
    Create(NULL, "Using an Event Object", 
    WS_OVERLAPPEDWINDOW, rectDefault, 
    NULL, "ThreadMenu"); 
    
    //     
    if(SLoadAccelTable("ThreadMenu")) 
    MessageBox("Cannot Load Accelerators", "Error"); 
    m_X = m_Y = 0; 
    maxX = GetSystemMetrics(SM_CXSCREEN) ; 
    maxY = GetSystemMetrics(SM_CYSCREEN) ; 
    CClientDC DC (this) ; 
    
    //     
    m_memDC.CreateCompatibleDC(&DC) ; 
    m bmp.CreateCompatibleBitmap(&DC, maxX, maxY) ; 
    m memDC.SelectObject(&m bmp); 
    
    //    
    m_bkbrush.CreateStockObject(WHITE_BRUSH) ; 


    14.                                        389 


    m memDC.SelectOoject(&m bkbrush); 
    
    //     
    m_memDC.PatBIt(0, 0, maxX, maxY, PATCOPY); 
                                                  ; 
    
    //   
    BOOL CApp::Initlnstance () 
    ( 
    m pMainWnd = new CMainMin; 
    m pMainWnd->ShowWindow (m nCrndShow) ; 
    m_pMainWnd->UpdateWindow() ; 
    return TRUE; 
    ) 
    
    //     
    BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd) 
    ON_WM_PAINT() 
    ON_WM_LBUTTONDOWN() 
    ON_COMMAND(IDM_THREAD, OnThread) 
    ON_COMMAND(IDM_EXIT, OnExit) 
    
    ON_COMMAND(IDM_HELP, OnHelp) 
    END_MESSAGE_MAP() 
    //       
    afx msg void CMainHin::OnPaint() 
    { 
    CPaintDC DC (this) ; 
    DC.BitBltfO, 0, , , &m_memDC, , , SRCCOPY) ; 
    } 
    //      
    //      
    afx_msg void CMainMin::OnLButtonDown(UINT Flags, CPoint Loc) 
    { 
    m_X = Loc.x; 
    m Y = Loc.y; 
    } 
    
    //   IDM_EXIT 
    afx msg void CMainWin::OnExit () 
    ( 
    int response; 
    response = MessageBox ("Quit the Program?", "Exit", MB_YESNO) ; 
    
    if(response == IDYES)                                               ! 
    SendMessage(WM CLOSE); //                   ' 
    } 
    //   IDM HELP 


    390                                     MFC:   


    afx msg void CMainWin::OnHelp() 
    ( 
    MessageBox("Event Object", "Help"); 
    
    //   IDM THREAD 
    afx_msg void CMainWin::OnThread() 
    ( 
    AfxBeginThread(MyThreadI, this) ; 
    AfxBeginThread(MyThread2, this) ; 
    i 
    //    
    UINT MyThreadI(LPVOID MinObjPtr) 
    ( 
    int i; 
    TEXTMETRIC tm; 
    char str[255] ; 
    int Tid = FirstThreadID; 
    FirstThreadID++; 
    CMainMin *ptr = (CMainMin *) WinObjPtr; 
    
    //    
    ptr->m memDC.GetTextMetrics(&tm) ; 
    CSingleLock SyncOb(&(ptr->Event)) ; 
    SyncOb.Lock (); //   
    
    for(i=0; i<10; i++) { 
    Sleep (500) ; 
    wsprintf(str, "First Thread #%d, beep #%d", Tid, i) ; 
    ptr->m_memDC.TextOut(ptr->m_X, ptr->m_Y, str, strlen (str)) ; 
    ptr->m Y = ptr->m_Y + tm.tmHeight + tm.tmExternalLeading; 
    ptr->InvalidateRect(NULL) ; 
    MessageBeep(MB_OK) ; 
    ) 
    FirstThreadID--; 
    SyncOb.Unlock (); //    
    return 0; 
    } 
    //    
    UINT MyThread2(LPVOID WinObjPtr) 
    ( 
    int i; 
    TEXTMETRIC tm; 
    char str[255] ; 
    inb Tid = SecondThreadID; 


    74.                                         391 


    SecondThreadID++;                                                 ' 
    CMainWin *ptr = (CMainWin *) WinObjPtr;                           | 
    
    //                                           1 
    ptr->ni_memDC . GetTextMetrics (?tm) ;                                  { 
    [ 
    
    for(i=0; i<10; i++) {                                              | 
    Sleep(200);                                                    j 
    wsprintf(str, "Second Thread #%d, beep #%d", Tid, i);          ' 
    ptr->m_memDC.TextOut(ptr->m_X, ptr->m_Y, str, strlen (str));    ; 
    ptr->m_Y = ptr->m_Y + tm.tmHeight + tm.tmExternalLeading; 
    ptr->InvalidateRect(NULL); 
    
    MessageBeep(MB_OK);                                            , 
    }                                                                  :. 
    SecondThreadID--;                                                  : 
    ptr->Event.SetEvent (); //    
    return 0; 
    } 
     ; //                             ' 

              
 Win32,     .   
          
.  ,  , ,    
    .  ,  
  ,    ( 
  - ; )     
. ,     . 
          . 
    
    392                                    MFC:  