在多线程编程中,常常会遇到需要给线程函数传递参数,传送一个结构体给一个线程函数也是可能的,可以通过传送一个指向结构体的指针参数来完成。先定义一个结构体:
struct ThreadParams
{
UINT nMilliSecond;
CProgressCtrl *pCtrlProgress;
};
用实例来说明,新建一个CThreadPassParameterDlg的对话框工程,
在对话框中加入一个编辑框
IDC_MILLISECOND
,一个按钮
IDC_START
,标题为
“
开始
”
,一个进度条
IDC_PROGRESS1
;打开
ClassWizard
,为编辑框
IDC_MILLISECOND
添加
int
型变量
m_nMilliSecond
,为进度条
IDC_PROGRESS1
添加
CProgressCtrl
型变量
m_ctrlProgress
;
在CThreadPassParameterDlg的头文件加(类的外部):
struct ThreadParams
{
UINT nMilliSecond;
CProgressCtrl *pCtrlProgress;
};
DWORD ThreadFun(LPVOID lpParam);
并在类内定义:
HANDLE m_hThread;
DWORD m_threadID;
ThreadParams m_params;
在函数 BOOL
CThreadPassParameterDlg::OnInitDialog() 中添加语句:
m_ctrlProgress.SetRange(0, 99);
m_nMilliSecond = 10;
UpdateData(FALSE);
在
CThreadPassParameterDlg类实现的外面添加:
DWORD ThreadFun(LPVOID lpParam)
{
ThreadParams* param = (ThreadParams*)lpParam;
for ( int i=0; i<100; i++)
{
int nTemp = param->nMilliSecond;
param->pCtrlProgress->SetPos(i);
Sleep(nTemp);
}
return (DWORD)0;
}
添加开始按钮的响应函数:
void CThreadPassParameterDlg::OnBtnStart()
{
UpdateData(TRUE);
m_params.nMilliSecond = m_nMilliSecond;
m_params.pCtrlProgress = &m_ctrlProgress;
m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFun, &m_params, 0, &m_threadID);
/*
GetDlgItem(IDC_BTN_START)->EnableWindow(FALSE);
WaitForSingleObject(m_hThread, INFINITE);
GetDlgItem(IDC_BTN_START)->EnableWindow(TRUE);
*/
}
顺便解释下WaitForSingleObject函数,
WaitForSingleObject
函数,其函数原型为:
DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);
hHandle 为要监视的对象(一般为同步对象,也可以是线程)的句柄;
dwMilliseconds 为 hHandle 对象所设置的超时值,单位为毫秒;
当在某一线程中调用该函数时,线程暂时挂起,系统监视 hHandle 所指向的对象的状态 。
如果在挂起的 dwMilliseconds 毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds 毫秒,但 hHandle 所指向的对象还没有变成有信号状态,函数照样返回。参数 dwMilliseconds 有两个具有特殊意义的值:0 和 INFINITE 。若为 0,则该函数立即返回;若为 INFINITE,则线程一直被挂起,直到 hHandle 所指向的对象变为有信号状态时为止。
如果你在 void CThreadPassParameterDlg::OnStart() 函数中添加/* */语 句 ,编译运行你就会发现进度条不进行刷新,主线程也停止了反应。什么原因呢?这是因为WaitForSingleObject 函数等待子线程( ThreadFunc )结束时,导致了线程死锁。因为WaitForSingleObject 函数会将主线程挂起(任何消息都得不到处理),而子线程 ThreadFunc正在设置进度条,一直在等待主线程将刷新消息处理完毕返回才会检测通知事件。这样两个线程都在互相等待,死锁发生了,编程时应注意避免。