线程
- 每个线程都有自己独立的 堆栈
关键函数
CreateThread/_beginthreadex 创建线程
ExitThread/_endthreadex 退出线程
SuspendThread 挂起线程
ResumeThread 恢复线程
TerminateThread 终止线程
GetCurrentThread 获取当前线程句柄(伪)
GetCurrentThreadId 获取当前线程ID
GetExitCodeThread 获取线程退出码
单独释放句柄
- 线程和线程句柄(Handle)不是一个东西,线程句柄是一个内核对象。
- 我们可以通过句柄来操作线程,但是线程的生命周期和线程句柄的生命周期不一样的
- 线程的生命周期就是线程函数从开始执行到return,线程句柄的生命周期是从CreateThread返回到你CloseHandle()。
- 所有的内核对象(包括线程Handle)都是系统资源,如果不释放句柄,系统的句柄资源很快就用光了。
- 如果你CreateThread以后需要对这个线程做一些操作,比如改变优先级,被其他线程等待,强制TermateThread等,就要保存这个句柄,使用完了在CloseHandle
- 如果你开了一个线程,而不需要对它进行如何干预,CreateThread后直接CloseHandle就行了。
CloseHandel(ThreadHandle )
只是关闭了一个线程句柄对象,表示我不再使用该句柄,即不对这个句柄对应的线程做任何干预了。并没有结束线程。
win api 创建线程
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
__drv_aliasesMem LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
线程退出的方案
线程自己结束
推荐,释放所有占用的内存
ExitThread
相当于直接return,但是不会释放内存(c++ 对象)
TerminateThread
- 拥有线程的进程终止运行之前,系统不撤销线程堆栈
- DLL接不到通知
- 异步运行,不能保证线程什么时候被结束
- 通过
WaitForSingleObject(m_hThread, INFINITE)
来等待某个线程结束
TerminateProcess
通过关闭 进程直接关闭所有线程
实例
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
//自定义线程函数
DWORD WINAPI ThreadProc(LPVOID lpParameter) // thread data);
{
char szBuf[256] = { 0 };
DWORD tid = GetCurrentThreadId();
wsprintfA(szBuf, "thread id : %d", tid);
while (true) {
OutputDebugStringA(szBuf);
Sleep(1000);
}
return 0;
}
void MainWindow::on_create_clicked()
{
DWORD dwThreadID = 0;
//创建线程
m_hThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadProc,
NULL,
CREATE_SUSPENDED,
&dwThreadID);
}
void MainWindow::on_pause_clicked()
{
SuspendThread(m_hThread);
}
void MainWindow::on_ternimate_clicked()
{
TerminateThread(m_hThread, 123);
}
void MainWindow::on_resume_clicked()
{
ResumeThread(m_hThread);
}
void MainWindow::on_pushButton_clicked()
{
DWORD dwExit;
WaitForSingleObject(m_hThread, INFINITE);
BOOL bRet =GetExitCodeThread(m_hThread, &dwExit);
qDebug() << dwExit << endl;
}