由于VS2017编译器的问题,本次开发环境在QT5.7.0.0下
CThread项目:
- CThread.h
#ifndef CTHREAD_H
#define CTHREAD_H
#include <windows.h>
//#include <Windows.h>
const int STATE_RUNNING = 0x0001; //设置运行标志, 说明线程正在运行
const int STATE_READY = 0x0002; //设置就绪状态, 说明线程正在加入调用方
const int STATE_BLOCKED = 0x0004; //设置阻塞标志, 说明线程被挂起
const int STATE_ALIVE = 0x0008; //设置激活标志, 说明线程被创建
const int STATE_ASYNC = 0x0010; //设置异步标志, 说明线程将并发执行, 即在线程返回之前, 调用方不会阻塞线程
const int STATE_SYNC = 0x0020; //设置同步标志, 说明线程将不会并发执行, 即调用方在线程返回之前将一直阻塞
const int STATE_CONTINUOUS = 0x0040; //设置连续标志, 说明线程将连续工作永不停止, 或者至少在进程退出前一直运行
//需要执行同步时用到该类
class CLock
{
public:
CLock();
~CLock();
private:
HANDLE hMutex;
};
class CThread
{
public:
CThread() : hThread(0), dwThreadId(0), dwState(0),
lpUserData(0), lpParameter(0) { }
HANDLE Create(LPVOID lpParameter,
DWORD dwInitialState = STATE_ASYNC, DWORD dwCreationFlag = 0); //创建实际的线程
void Join(DWORD dwWaitinterval = INFINITE);
DWORD Suspend();
DWORD Resume();
void SetUserData(void* lpUserData);
void* GetUserData() const;
DWORD GetId() const;
HANDLE GetHandle() const;
DWORD GetAsyncState() const;
DWORD GetState() const;
void SetState(DWORD dwNewState);
BOOL Alert();
protected:
virtual void Run(LPVOID lpParameter = 0) = 0; //为了派生类用
LPVOID lpParameter;
private:
//必须为static, 因为第1个参数都是隐式参数this(即不显示)
static DWORD WINAPI StartAddress(LPVOID lpParameter);
HANDLE hThread;
DWORD dwThreadId;
DWORD dwState;
void* lpUserData;
HANDLE hEvent;
};
//返回一个唯一的线程标识
inline DWORD CThread::GetId() const
{
return dwThreadId;
}
//返回一个线程句柄
inline HANDLE CThread::GetHandle() const
{
return hThread;
}
#endif // CTHREAD_H
- CThread.cpp
#include "CThread.h"
//如果另有线程也需要互斥量, 那么在互斥量释放之前, 这个需要互斥量的线程将被阻塞
CLock::CLock()
{
//第二个参数为FALSE, 一旦创建了一个互斥量, 该线程就不再拥有其所有权
hMutex = CreateMutex(NULL, FALSE, TEXT("_tmp_mutex_lock_"));
WaitForSingleObject(hMutex, INFINITE); //调用此函数才能拥有互斥量的所有权
}
CLock::~CLock()
{
ReleaseMutex(hMutex); //释放互斥量
CloseHandle(hMutex); //关闭互斥量的句柄
}
//第一个参数必须的, 稍后该参数将被传给StartAddress,线程从这里开始执行
//第二个参数代表线程执行方法, 如果设置为STATE_SYNC, 就使用CLock类对象
//第三参数设置线程状态: 默认0表示创建该线程后立即使用它
// STATE_BLOCKED创建一个处于挂起状态的线程
// STATE_CONTINUOUS创建事件,若存在则打开事件对象
HANDLE CThread::Create(LPVOID lpParameter, DWORD dwInitialState,
DWORD dwCreationFlag)
{
dwState |= dwInitialState;
this->lpParameter = lpParameter;
if (dwState & STATE_ALIVE)
{
return hThread;
}
hThread = CreateThread(NULL, 0, StartAddress, this,
dwCreationFlag, &dwThreadId);
dwState |= STATE_ALIVE;
if (dwState & STATE_CONTINUOUS)
{
hEvent = CreateEvent(NULL, TRUE, FALSE, TEXT("__tmp_event__"));
}
return hThread;
}
//设置STATE_READY标志, 并等待线程对象成为已触发状态
//或在dwWaitInterval时间间隔内一直等待
//dwWaitInterval默认INFINITE
void CThread::Join(DWORD dwWaitInterval)
{
if (dwState & STATE_BLOCKED)
{
return;
}
if (dwState & STATE_READY)
{
return;
}
dwState |= STATE_READY;
WaitForSingleObject(hThread, dwWaitInterval);
dwState ^= STATE_READY;
}
//挂起线程
//设置STATE_BLOCKED
DWORD CThread::Suspend()
{
if (dwState & STATE_BLOCKED)
{
return DWORD(-1);
}
if (dwState & STATE_READY)
{
return DWORD(-1);
}
DWORD dwSuspendCount = SuspendThread(hThread);
dwState |= STATE_BLOCKED;
return dwSuspendCount;
}
//恢复线程
//复原STATE_BLOCKED
DWORD CThread::Resume()
{
if (dwState & STATE_RUNNING)
{
return DWORD(-1);
}
DWORD dwSuspendCount = ResumeThread(hThread);
dwState ^= STATE_BLOCKED;
return dwSuspendCount;
}
//设计lpUserData,为了将来方便设置用户指定的数据
//设置用户的数据值
void CThread::SetUserData(void* lpUserData)
{
this->lpUserData = lpUserData;
}
//获取用户的数据值
void* CThread::GetUserData() const
{
return lpUserData;
}
//返回对象的异步状态
DWORD CThread::GetAsyncState() const
{
if (dwState & STATE_ASYNC)
{
return STATE_ASYNC;
}
return STATE_SYNC;
}
//处理额外的对象状态
//获取dwState值或对象状态
DWORD CThread::GetState() const
{
return dwState;
}
//设置dwState值或对象状态
void CThread::SetState(DWORD dwNewState)
{
dwState = 0;
dwState |= dwNewState;
}
//把事件的状态改为signaled
//处理使用了STATE_CONTINUOUS情况
BOOL CThread::Alert()
{
return SetEvent(hEvent);
}
DWORD WINAPI CThread::StartAddress(LPVOID lpParameter)
{
CThread* cThread = (CThread*)lpParameter;
if (STATE_SYNC == cThread->GetAsyncState())
{
if (cThread->dwState & STATE_CONTINUOUS)
{
DWORD dwWaitStatus = 0;
while (TRUE)
{
cThread->Run();
dwWaitStatus = WaitForSingleObject(cThread->hEvent, 10);
if (WAIT_OBJECT_0 == dwWaitStatus)
{
break;
}
}
return 0;
}
cThread->Run();
return 0;
}
if (cThread->dwState & STATE_CONTINUOUS)
{
DWORD dwWaitStatus = 0;
while (TRUE)
{
CLock lock;
{
cThread->Run();
}
dwWaitStatus = WaitForSingleObject(cThread->hEvent, 10);
if (WAIT_OBJECT_0 == dwWaitStatus)
{
break;
}
}
return 0;
}
//多此一举了,去掉大括号一样的意义
CLock lock;
{
cThread->Run();
}
return 0;
}
- main.cpp
#include "CThread.h"
class Thread : public CThread
{
protected:
virtual void Run(LPVOID lpParameter = 0);
};
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
case WM_CLOSE:
{
DestroyWindow(hWnd);
break;
}
default:
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
return 0;
}
//纯虚函数 使其行为更像一个非静态方法
void Thread::Run(LPVOID lpParameter)
{
WNDCLASSEX wndEx = { 0 };
wndEx.cbClsExtra = 0;
wndEx.cbSize = sizeof(WNDCLASSEX);
wndEx.cbWndExtra = 0;
wndEx.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
wndEx.hCursor = LoadCursor(NULL, IDC_ARROW);
wndEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wndEx.hInstance = GetModuleHandle(NULL);
wndEx.lpfnWndProc = WindowProcedure;
wndEx.lpszClassName = (LPCTSTR)this->lpParameter;
wndEx.lpszMenuName = NULL;
wndEx.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
if (!RegisterClassEx(&wndEx))
{
return;
}
HWND hWnd = CreateWindow(wndEx.lpszClassName, TEXT("Basic Thread Management"), WS_OVERLAPPEDWINDOW,
200, 200, 800, 600, HWND_DESKTOP, NULL, wndEx.hInstance, NULL);
UpdateWindow(hWnd);
ShowWindow(hWnd, SW_SHOW);
MSG msg = { 0 };
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnregisterClass(wndEx.lpszClassName, wndEx.hInstance);
}
int main()
{
Thread thread;
thread.Create((LPVOID)TEXT("WND_CLASS_1"));
Thread pthread;
pthread.Create((LPVOID)TEXT("WND_CLASS_2"));
thread.Join();
pthread.Join();
return 0;
}
- 运行结果:需要关闭2次