今天学习的时候看到了一个例子,通过子线程来设置CProgressCtrl的进度,其中有一个关于死锁的问题不太明白,代码大致如下:struct threadInfo
{
UINT nMilliSecond;
CProgressCtrl* pctrlProgress;
};void CMy1_18_1Dlg::OnStart()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
Info.nMilliSecond=m_nMilliSecond;
Info.pctrlProgress=&m_ctrlProgress;
hThread=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFunc,
&Info,
0,
&ThreadID);
// GetDlgItem(IDC_START)->EnableWindow(FALSE);
// WaitForSingleObject(hThread,INFINITE);
// GetDlgItem(IDC_START)->EnableWindow(TRUE);
} //这个是“开始”按钮的响应函数,用它来启动一个线程,设置进度条
UINT ThreadFunc(LPVOID lpParam) {
threadInfo* pInfo=(threadInfo*)lpParam; for(int i=0;i<100;i++)
{
int nTemp=pInfo->nMilliSecond;
pInfo->pctrlProgress->SetPos(i);
Sleep(nTemp);
}
return 0;
}// 这个是线程函数不太明白的地方是OnStart函数中被注释掉的部分,资料上说如果不注释掉会导致死锁,试验的结果的确是会这样,为什么在子线程中设置进度条会死锁呢?难道这个过程还需要和主线程交互?
{
UINT nMilliSecond;
CProgressCtrl* pctrlProgress;
};void CMy1_18_1Dlg::OnStart()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
Info.nMilliSecond=m_nMilliSecond;
Info.pctrlProgress=&m_ctrlProgress;
hThread=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFunc,
&Info,
0,
&ThreadID);
// GetDlgItem(IDC_START)->EnableWindow(FALSE);
// WaitForSingleObject(hThread,INFINITE);
// GetDlgItem(IDC_START)->EnableWindow(TRUE);
} //这个是“开始”按钮的响应函数,用它来启动一个线程,设置进度条
UINT ThreadFunc(LPVOID lpParam) {
threadInfo* pInfo=(threadInfo*)lpParam; for(int i=0;i<100;i++)
{
int nTemp=pInfo->nMilliSecond;
pInfo->pctrlProgress->SetPos(i);
Sleep(nTemp);
}
return 0;
}// 这个是线程函数不太明白的地方是OnStart函数中被注释掉的部分,资料上说如果不注释掉会导致死锁,试验的结果的确是会这样,为什么在子线程中设置进度条会死锁呢?难道这个过程还需要和主线程交互?
// WaitForSingleObject(hThread,INFINITE);主线程等待子线程结束,子线程中调用pInfo->pctrlProgress->SetPos(i);来SendMessage发送PBM_SETPOS消息到UI主线程,子线程等待主线程处理该消息然后再返回,但是而这个时候主线程又在等待子线程结束,从而导致死锁发生。
系统窗口API本身就是通过SendMessage来实现的
如SetWindowText,就是通过SendMessage WM_SETTEXT实现的
而不是直接读取HWND对应的数据结构
子线程无限期停止执行,直到 hThread状态改变为止。