14 Wi n d o w s M F C 53 54 55 56 ( ) ( Wo r k e r T h r e a d ) 57 ( ) ( U s e r Interface Thread) 58 59 14.1 53 1. 2. C l a s s Wi z a r d O n I d l e () 3. Class Wi z a r d O n I d l e () O n I d l e () BOOL CWzdApp::OnIdle( LONG lcount ) // clean up temporary objects while (!m_templist.isempty() )
332 delete m_te m p L i s t. R e m o v e H e a d ( ) ; return CWinApp::OnIdle( lcount ); 4. O n I d l e () C Wi n A p p :: O n I d l e (), ( s h e l l ) O n I d l e () O n I d l e ( 5. W z d. c p p O n I d l e () ( ) W z d Te s t O n I d l e () 14.2 54 1. 2. M F C M F C Wi n d o w s A P I :: WinExec () A P I :: Wi n E x e c () A P I ::CreateProcess () 3. 1) :: WinExec () :: WinExec () W z d. b a t CString str; str = "Wzd.bat"; // execute a batch file if ( ::Wi n E x e c ( e l s e s t r, SW_NORMAL ) // command line // see ShowWindow for other options >31 ) // numbers lower then 31 are failures AfxMessageBox( "Successfully created." ); AfxMessageBox( "Failed to create process." ); 2) :: C r e a t e P r o c e s s ()
14 333 CString str; S TA RTUPINFO si; P R O C E S S _ I N F O R M ATION pi; // specify command str = "Wzd.bat"; // zero out and initialize STA RT U P I N F O memset( &si, 0, sizeof( si ) ); si.cb = sizeof( si ); si.dwflags = STA RT F _ U S E S H O W W I N D O W; s i. w S h o w Window = SW_SHOW; if ( CreateProcess( N U L L, // can be name of process unless // batch file, else must be // in command line: ( char * )LPCSTR( str ), // command line N U L L, N U L L, FA L S E, N O R M A L _ P R I O R I T Y _ C L A S S, N U L L, N U L L, & s i, & p i ) ) AfxMessageBox( "Successfully created." ); HANDLE ph = pi.hprocess; // wait until application is ready for input if (!WaitForInputIdle( ph,1000 ) ) e l s e // send messages, etc. // kill process with 0 exit code TerminateProcess( ph, 0 ); AfxMessageBox( "Failed to create process." ); 3) // security options // if true will inherit all // inheritable handles // from this process // can also be HIGH_PRIORITY_CLASS // or IDLE_PRIORITY_CLASS // inherit this process's // environment block // specifies working directory // of created process // STA RTUPINFO specified above // PROCESS_INFORMATION returned Windows API :: G e t M o d u l e F i l e N a m e ()
334 // change directory to this application's.exe file char szbuff e r [ 1 2 8 ] ; ::GetModuleFileName( AfxGetInstanceHandle(), szbuff e r, sizeof( szbuffer ) ); char *p = strrchr( szbuff e r, '\\' ); *p = 0; S Z B u ff e r _ c h d i r ( s z B u ff e r ) ; 4. Wi n E x e c () S h o w Wi n d o w () S W _ H I D E, SW_MAXMIZE, SW_MINIMIZE A P I \ C:\Program Files\Microsoft Off i c e \ p r o g. e x e "C:\Program Files\Microsoft Off i c e \ p r o g. e x e " C M D. E X E :: C r e a t e P r o c e s s () Te r m i n a t e P r o c e s s () M F C ( 58 ) Te r m i n a t e P r o c e s s () Wi n d o w s 57 49 50 5. M a i n f r m. c p p O n W z d 1 Te s t () O n W z d 2 Te s t () Te s t W z d 1 W z d 2 w z d. b a t 14.3 55 1.
14 335 2. ::SetPriority() API :: S e t T h r e a d P r i o r i t y () API 3. 1) ::SetPriorityClass( : : G e t C u r r e n t P r o c e s s ( ), // process handle // REALT I M E _ P R I O R I T Y _ C L A S S // highest: thread must run // immediately before any // other system task // HIGH_PRIORITY_CLASS // high: time-critical threads // NORMAL_PRIORITY_CLASS // normal: thread with equal I D L E _ P R I O R I T Y _ C L A S S ) ; DWORD priority = : : G e t P r i o r i t y C l a s s ( // importance to other // system applications // low: threads that can run in // the background of the // entire system : : G e t C u r r e n t P r o c e s s ( ) // process handle ) ; 2) S e t T h r e a d P r i o r i t y ( T H R E A D _ P R I O R I T Y _ T I M E _ C R I T I C A L T H R E A D _ P R I O R I T Y _ H I G H E S T T H R E A D _ P R I O R I T Y _ A B O V E _ N O R M A L T H R E A D _ P R I O R I T Y _ N O R M A L T H R E A D _ P R I O R I T Y _ B E L O W _ N O R M A L T H R E A D _ P R I O R I T Y _ L O W E S T T H R E A D _ P R I O R I T Y _ I D L E ) ; 4. // highest priority // next highest // etc... // lowest priority C P U C P U C P U 5. W z d. c p p S e t P r i o r i t y C l a s s () F i l e / O p e n
336 Windows Explorer 14.4 56 1. C P U 2. A f x B e g i n T h r e a d () Wi n d o w s 3. 1) typedef struct t_threaddata HWND hdonewnd; int ndata; THREADDATA ; // window handle of main app to send messages // data to process p P a r a m UINT WzdThread( LPVOID pparam ) // get data from thread creator T H R E A D D ATA *pdata = ( THREADDATA * )pparam; // do calulations for ( int i = pdata -> ndata;i < 1000000;i++ ) // save data back to thread creator pdata -> ndata = i; // tell creator we re done ::SendMessage( pdata -> hdonewnd, WM_DONE, 0, 0 ); return 0; G e t E x i t T h r e a d () A f x E n d T h r e a d ( a rg ) a rg 2) A f x B e g i n T h r e a d () T H R E A D D ATA m_threaddata;
14 337 : : : ThreadData.nData = 123; ThreadData.hDoneWnd = m_hwnd; A f x B e g i n T h r e a d ( W z d T h r e a d, & m _ T h r e a d D a t a ) ; // static thread process declare // data to send to thread 3) Wi n d o w s #define WM_DONE WM_USER + 1 // tell creator we re done ::SendMessage( pdata -> hdonewnd, WM_DONE, 0, 0 ); O N _ M E S S A G E _ V O I D () C l a s s Wi z a r d BEGIN_MESSAGE_MAP( CWzdVi e w, CView ) // AFX_MSG_MAP( CWzdView ) // AFX_MSG_MAP ON_MESSAGE_VOID( WM_DONE,OnDone ) E N D _ M E S S A G E _ M A P ( ) void CWzdVi e w : : O n D o n e ( ). h ON_MESSAGE_VOID() O N _ M E S S A G E ( ) 4. C W n d C W n d C W n d C W n d 59 A f x B e g i n T h r e a d () C Wi n T h r e a d A f x E n d T h r e a d () ::PostQuitMessage () 51 5 2 all done O N _
338 MESSAGE () L R E S U LT CMainFrame::OnDone( WPARAM wparam,lparam lparam ) return 0; 5. W z d v i e w. c p p O n Te s t W z d () O n D o n e () Te s t W z d #ifndef WZDTHREAD_H #define WZDTHREAD_H #define WM_DONE WM_USER + 1 typedef struct t_threaddata HWND hdonewnd; int ndata; THREADDATA ; UINT WzdThread( LPVOID pparam ); # e n d i f // WzdThread.cpp : thread process / / #include "stdafx.h" #include "WzdThread.h" / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / // CWzdThread UINT WzdThread( LPVOID pparam ) // get data from thread creator T H R E A D D ATA *pdata = ( THREADDATA * )pparam; // do calulations for ( int i = pdata -> ndata;i < 1000000;i++ ) // save data back to thread creator pdata -> ndata = i; // tell creator we re done ::SendMessage( pdata -> hdonewnd, WM_DONE, 0, 0 ); return 0; // return value up to you parent can retrieve with GetExitCodeThread(); // can also call AfxEndThread(0) where the meaning of the argument is up to you
14 339 14.5 57 1. 2. AfxBegin Thread () 56 C Wi n T h r e a d 3. 1) C l a s s Wi z a r d C Wi n T h r e a d 2) C WinThread *pthread = AfxBeginThread( RUNTIME_CLASS( CWzdThread ) ); :: P o s t Q u i t M e s s a g e ( a rg ) a rg a rg int arg = pthread -> GetExitCodeThread(); W i n d o w s ::PostQuitMessage (arg) 58 4. ( ) 5. Te s t W z d 6. #if!defined( AFX_WZDTHREAD_H 411 A E 4 C 2 _ E 5 1 5 _ 11D1_9B80_00AA003D8695 INCLUDED_ )
340 #define AFX_WZDTHREAD_H 411 A E 4 C 2 _ E 5 1 5 _ 11 D 1 _ 9 B 8 0 _ 0 0 A A 0 0 3 D 8 6 9 5 I N C L U D E D _ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 // WzdThread.h : header file // #include "WzdDialog.h" / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / // CWzdThread thread class CWzdThread : public CWi n T h r e a d D E C L A R E _ D Y N C R E ATE( CWzdThread ) p r o t e c t e d : CWzdThread(); // protected constructor used by dynamic creation // Attributes p u b l i c : // Operations p u b l i c : // Overrides // ClassWizard generated virtual function overrides // AFX_VIRTUAL( CWzdThread ) p u b l i c : virtual BOOL InitInstance(); virtual int ExitInstance(); // AFX_VIRT U A L // Implementation p r o t e c t e d : virtual ~CWzdThread(); // Generated message map functions // AFX_MSG( CWzdThread ) // NOTE - the ClassWizard will add and remove member functions here. // AFX_MSG D E C L A R E _ M E S S A G E _ M A P () p r i v a t e : CWzdDialog m_dlg; ; / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / // AFX_INSERT _ L O C AT I O N // Microsoft Developer Studio will insert additional declarations immediately
14 341 // before the previous line. # e n d i f //!defined( AFX_WZDTHREAD_H 411 A E 4 C 2 _ E 515 _ 11D1_9B80_00AA003D8695 INCLUDED_ ) // WzdThread.cpp : implementation file // #include "stdafx.h" #include "wzd.h" #include "WzdThread.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = FILE ; # e n d i f / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / // CWzdThread I M P L E M E N T _ D Y N C R E ATE( CWzdThread, CWinThread ) C W z d T h r e a d : : C W z d T h r e a d ( ) C W z d T h r e a d : : ~ C W z d T h r e a d ( ) BOOL CWzdThread::InitInstance() m_dlg.create( IDD_WZD_DIALOG ); m _ d l g. S h o w Window( SW_SHOW ); m_pmainwnd = &m_dlg; return TRUE; // can end thread by returning FALSE here int CWzdThread::ExitInstance() m _ d l g. D e s t r o y Wi n d o w (); return CWi n T h r e a d :: E x i t I n s t a n c e (); BEGIN_MESSAGE_MAP( CWzdThread, CWinThread ) // AFX_MSG_MAP( CWzdThread ) // NOTE - the ClassWizard will add and remove mapping macros here. // AFX_MSG_MAP E N D _ M E S S A G E _ M A P ()
342 14.6 58 1. 2. C W n d :: S e n d M e s s a g e () S e n d M e s s a g e ( C Wi n T h r e a dp o s t T h r e a d M e s s a g e () P o s t T h r e a d M e s s a g e () SendMessage () 3. #define WM_WZDKILLTHREAD WM_USER + 1 C Wi n T h e a d m_pthread = AfxBeginThread( RUNTIME_CLASS( CWzdThread ) ); P o s t T h r e a d M e s s a g e () m_pthread -> PostThreadMessage( WM_WZDKILLTHREAD, 0, 0 ); C l a s s Wi z a r d BEGIN_MESSAGE_MAP( CWzdThread, CWinThread ) // AFX_MSG_MAP( CWzdThread ) // AFX_MSG_MAP ON_THREAD_MESSAGE( WM_WZDKILLTHREAD,OnKillThread ) E N D _ M E S S A G E _ M A P ( ) :: P o s t Q u i t M e s s a g e () L R E S U LT CWzdThread::OnKillThread( WPARAM wparam,lparam lparam ) ::PostQuitMessage( 0 ); return 0; // returned to PostThreadMessage() 4. P o s t T h r e a d M e s s a g e () b K i l l ( 49 ) ON_REGISTER_THREAD_MESSAGE( registered_message_id, process )
14 343 5. Te s t W z d E n d 14.7 59 1. 2. M F C C M u t e x C S i n g l e L o c k C M u l t i L o c k 3. C M u t e x class CWzdData : public CObject ; : : : // synchronization protection CMutex m_mutex; : : : void CWzdData::GetData( int *pint,float *pfloat,dword *pword ) *pint = m_nint; *pfloat = m_ffloat; * p Word = m_dwwo r d ; void CWzdData::SetData( int nint,float ffloat,dword dwword ) m_nint = nint; m_ffloat = ffloat; m _ d w Word = dwwo r d ; C M u t e x S e t D a t a () C S i n g l e L o c k C S i n g l e L o c k L o c k ( ) BOOL CWzdData::SetData( int nint,float ffloat,dword dwword ) CSingleLock slock( &m_mutex ); if ( slock.lock( 1000 ) ) // timeout in milliseconds,
344 // default = INFINITE // set values can also be lists and arrays m_nint = nint; m_ffloat = ffloat; m _ d w Word = dwwo r d ; return TRUE; return FA L S E ; // timed out! // unlocks on return or you can call slock.unlock(); L o c k () L o c k () FA L S E C M u t e x C M u l t i L o c k CMutex mutex[2]; mutex[0] = &mutex1; mutex[1] = &mutex2; CMultiLock mlock( mutex,2 ); if ( mlock.lock( 1000 ) ) // where 2 is the number of mutexes 4. C M u t e x 1 C M u t e x 3 : : C r e a t e M u t e x () Windows API :: C r e a t e M u t e x () M u t e x 51 Wi n d o w s C O b L i s t 5. W z d D a t a. c p p G e t D a t a () Te s t W z d 6. #ifndef WZDDATA _ H #define WZDDATA _ H #include <afxmt.h> class CWzdData : public CObject p u b l i c : DECLARE_SERIAL( CWzdData ) C W z d D a t a ( ) ;
14 345 BOOL GetData( int *pint,float *pfloat,dword *pword ); BOOL SetData( int nint,float ffloat,dword dwword ); // synchronization protection CMutex m_mutex; // result data int m_nint; float m_ffloat; DWORD m_dwwo r d ; ; # e n d i f // WzdData.cpp : implementation of the CWzdData class // #include "stdafx.h" #include "WzdData.h" / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / // CWzdData IMPLEMENT_SERIAL( CWzdData, CObject, 0 ) C W z d D a t a :: C W z d D a t a () m_nint = 0; m_ffloat = 0.0f; m _ d w Word = 0; BOOL CWzdData::GetData( int *pint,float *pfloat,dword *pword ) // we lock here too so that we ll never read half written data CSingleLock slock( &m_mutex ); if ( slock.lock( 1000 ) ) // timeout in milliseconds, default = INFINITE // get values can also be lists and arrays *pint = m_nint; *pfloat = m_ffloat; * p Word = m_dwwo r d ; return TRUE; return FALSE; // timed out! // unlocks on return or you can call slock.unlock();
346 BOOL CWzdData::SetData( int nint,float ffloat,dword dwword ) CSingleLock slock(&m_mutex); // or with CMultiLock can specify several // m_mutex s for waiting on several // data items if ( slock.lock( 1000 ) ) // timeout in milliseconds, // default = INFINITE // set values can also be lists and arrays m_nint = nint; m_ffloat = ffloat; m _ d w Word = dwwo r d ; return TRUE; return FALSE; // timed out! // unlocks on return or you can call slock.unlock();