MFC - 封装线程类: CThread

CThread.h

 1 #ifndef        _THREAD_H_2016_04_24
 2 #define        _THREAD_H_2016_04_24
 3 #pragma once
 4 
 5 class CThread
 6 {
 7 public:
 8     CThread();
 9     ~CThread();
10 
11 public:
12     void fnStart(DWORD dwCreationFlags = 0);                // 开始线程
13     void fnStop();                                          // 停止线程
14     void fnSuspend();                                       // 挂起线程
15     void fnResume();                                        // 恢复线程
16     virtual void fnRun() = 0;                               // 纯虚函数, 在派生类重载fnRun()函数, 利用C++的多态, 实际执行派生类的fnRun()
17     virtual void fnSetThreadData(DWORD dwParam);            // 设置: m_dwData
18     virtual DWORD fnGetThreadData();                        // 获取: m_dwData
19 
20 private:
21     static DWORD WINAPI fnThreadProc(LPVOID lpParameter);
22 
23 public:
24     HANDLE           m_hThread;           // 线程句柄
25     DWORD            m_dwThreadId;        // 线程ID
26     BOOL             m_bIsExit;         // 退出标识
27     BOOL             m_bIsSuspend;      // 挂起标识
28     DWORD            m_dwData;           // 如果需要外部传递数据进来:
29                                          //    1. 通过重载fnSetThreadData()设置m_dwData;
30                                          //    2. 通过fnGetThreadData()获取m_dwData;
31                                          //    3. 在派生类中重载fnRun时, 使用m_dwData;
32 };                                                            
33 
34 #endif        //_THREAD_H_2016_04_24

CThread.cpp

 1 #include "stdafx.h"
 2 #include "Thread.h"
 3 
 4 
 5 CThread::CThread()
 6 {
 7     m_hThread = NULL;               // 线程不存在
 8     m_dwThreadId = 0;                        
 9     m_bIsExit = FALSE;             // 未退出
10     m_bIsSuspend = FALSE;          // 未挂起
11 }
12 
13 CThread::~CThread()
14 {
15     fnStop();                    // 结束线程
16 }
17 
18 // 线程回调函数
19 DWORD WINAPI CThread::fnThreadProc(LPVOID lpParameter)
20 {
21     CThread *pThis = (CThread*)lpParameter;
22     ASSERT(pThis);
23     while ( !pThis->m_bIsExit )
24     {
25         pThis->fnRun();       // 线程真正在fnRun()函数内执行
26     }
27     return 88;
28 }
29 
30 // 设置线程数据
31 void CThread::fnSetThreadData(DWORD dwParam)
32 {
33     if (m_dwData != dwParam)
34     {
35         m_dwData = dwParam;
36     }
37 }
38 
39 // 获取线程数据
40 DWORD CThread::fnGetThreadData()
41 {
42     return m_dwData;
43 }
44 
45 // 开始线程
46 void CThread::fnStart(DWORD dwCreationFlags)
47 {
48     if (m_hThread) return;            // 如果线程存在,则不再创建
49     m_bIsExit = FALSE;                // 重置退出标识
50 
51     m_bIsSuspend = FALSE;    // 重置挂起标识
52     m_bIsSuspend = dwCreationFlags == CREATE_SUSPENDED ? TRUE : FALSE;        // 如果dwCreationFlags == CREATE_SUSPENDED, 则m_bIsSuspend == TRUE
53                                                                               // 线程处于挂起状态, fnStart()后需要调用fnResumeThread()恢复运行
54     HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)fnThreadProc, (LPVOID)this, dwCreationFlags, 0);
55     ASSERT(hThread);
56     m_hThread = hThread;
57 }
58 
59 // 停止线程
60 void CThread::fnStop()
61 {
62     if ( m_hThread )
63     {
64         fnResume();        // 防御性编程: 此处必须处理一次【恢复线程】操作, 防止线程在【挂起】状态下阻塞在WaitForSingleObject(), 无法正常退出;
65 
66         /*
67            m_bIsExit == TRUE; 线程执行体内循环结束, 所以必须放在fnResume()后执行;
68            目的 : 是保证线程在正常运行的状态下的正常退出;  线程在挂起状态下且m_bIsExit==TRUE 线程会阻塞在
69            WaitForSingleObject(), 无法正常退出...
70         */
71 
72         m_bIsExit = TRUE;
73         WaitForSingleObject(m_hThread, INFINITE);
74         CloseHandle(m_hThread);
75         m_hThread = NULL;
76     }
77 }
78 
79 // 挂起线程
80 void CThread::fnSuspend()
81 {
82     if (NULL == m_hThread) return;              // 如果线程不存在, 立即返回
83     if (TRUE == m_bIsSuspend)    return;        // 如果挂起, 则立即返回
84     SuspendThread(m_hThread);                   // 挂起线程
85     m_bIsSuspend = !m_bIsSuspend;              // TRUE: 标识线程已挂起
86 }
87 
88 // 恢复线程
89 void CThread::fnResume()
90 {
91     if (NULL == m_hThread) return;            // 如果线程不存在, 立即返回
92     if (FALSE == m_bIsSuspend) return;        // 如果未挂起, 则立即返回
93     ResumeThread(m_hThread);                  // 恢复线程
94     m_bIsSuspend = !m_bIsSuspend;             // FALSE: 标识线程已恢复
95 }

 

posted @ 2016-04-24 23:57  C/C++/Python/Java  阅读(1513)  评论(0编辑  收藏  举报