线程的暂停与挂起

这篇文章就给讲一下,线程的挂起函数SuspendThread唤醒函数ResumeThread

上一篇文章说到的 创建线程的函数,就相当于是给我们创建了一部小汽车。但是这部小汽车还没有刹车和一键启动,挂起函数SuspendThread唤醒函数ResumeThread 就好比是汽车的刹车与一键启动。

线程内核对象

线程内核对象就是一个包含了线程状态信息的数据结构,每一次对CreateThread函数的成功调用,系统都会在内部为新的线程分配一个内核对象。系统提供的管理线程的函数其实就是依靠访问线程内部对象来实现管理的。

线程内核对象中记录了线程内核对象的使用次数,以及指明线程的暂停次数,当调用Create Thread函数是,线程的内核对象就被创建了。

SuspendThread 挂起函数

SuspendThread函数挂起指定的线程。使用SuspendThread函数会使内核对象中的当前暂停次数 +1,函数执行完毕后返回 +1 前的次数。当线程的暂停计数大于0时,线程将处于暂停状态。

DWORD SuspendThread(
  HANDLEhThread   // 需要挂起的线程句柄
);

ResumeThread 唤醒函数

ResumeThread函数减少线程的挂起计数。使用ResumeThread函数会使内核对象中的当前暂停次数 - 1,函数执行完毕后返回 -1 前的次数。当暂停计数减为零时,线程将继续执行。

DWORD ResumeThread(
  HANDLEhThread   // handle to thread
);

下面用MFC写的一个有界面的测试程序,点击 启动线程 按钮后。线程就会不断循环累加并且打印 i 的值,点击 停止按钮 后,线程就会进入挂起状态,直到点击恢复按钮 线程才会继续执行打印操作。

代码如下:

UINT PrintFun(LPVOID pParam)//线程函数定义
{
	int i = 1;
	CString str;

	while (TRUE)
	{
		str.Format(_T("%d\n"), i);
		OutputDebugString(str);
		Sleep(50);
		i++;
	}

}


HANDLE hThread = NULL;  //保存线程句柄

//启动线程按钮响应函数
void CThreadMfcDlg::OnBnClickedOk()
{
	CWinThread* pThread = AfxBeginThread(PrintFun, NULL);
	hThread = pThread->m_hThread;

	// TODO: 在此添加控件通知处理程序代码
	//CDialog::OnOK();
}

//暂停按钮响应函数
void CThreadMfcDlg::OnBnClickedButton1()
{
	int x = SuspendThread(hThread);
	// TODO: 在此添加控件通知处理程序代码
}

//恢复按钮响应函数
void CThreadMfcDlg::OnBnClickedButton2()
{
	int x = ResumeThread(hThread);

	// TODO: 在此添加控件通知处理程序代码
}

单个线程可以被暂停若干次。如果一个线程被暂停了3次,它必须被唤醒3次才可以分配给一个CPU。