在多线程编程中,常常会遇到需要给线程函数传递参数,传送一个结构体给一个线程函数也是可能的,可以通过传送一个指向结构体的指针参数来完成。先定义一个结构体:
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正在设置进度条,一直在等待主线程将刷新消息处理完毕返回才会检测通知事件。这样两个线程都在互相等待,死锁发生了,编程时应注意避免。