我先把我的代码大致发一下吧://这个函数是按钮的响应函数,负责生成一个搜索过程的子线程
void CResourceDlg::OnBnClickedBtnSearch()
{
// TODO: Add your control notification handler code here
CString strSearchTxt;
GetDlgItemText(IDC_EDIT_SEARCH, strSearchTxt);//这是搜索关键字 SearchState();//这个函数设置一个枚举值,表示可以搜索了 strSearchTxt = strSearchTxt.Trim();
if (strSearchTxt.IsEmpty())
{
return;
} if (m_hSearchThread)//定义的成员变量,接收搜索子线程的句柄
{
WaitForSingleObject(m_hSearchThread, INFINITE);
m_hSearchThread = NULL;
} CSearchProcess *pSearchProcess = new CSearchProcess(this, strSearchTxt);
CWinThread *pWinThread = AfxBeginThread(SearchResourceProc, static_cast<LPVOID>(pSearchProcess));
if (pWinThread)
{
m_hSearchThread = pWinThread->m_hThread;
}
}
//这个函数是一个按钮的响应函数,负责停止搜索过程
void CResourceDlg::OnBnClickedBtnClose()
{
// TODO: Add your control notification handler code here
NormalState();//把状态改成非搜索模式,这样,子线程里面就可以知道要退出搜索了
if (m_hSearchThread)
{
DWORD dwRet = WaitForSingleObject(m_hSearchThread, INFINITE);//这里就死掉了
ASSERT(dwRet == WAIT_OBJECT_0);
m_hSearchThread = NULL;
}
}
线程的函数代码可以确定是正确的。因为不点这个停止搜索按钮的时候,是可以正常搜索的。可是一点停止搜索,就死锁了。
void CResourceDlg::OnBnClickedBtnSearch()
{
// TODO: Add your control notification handler code here
CString strSearchTxt;
GetDlgItemText(IDC_EDIT_SEARCH, strSearchTxt);//这是搜索关键字 SearchState();//这个函数设置一个枚举值,表示可以搜索了 strSearchTxt = strSearchTxt.Trim();
if (strSearchTxt.IsEmpty())
{
return;
} if (m_hSearchThread)//定义的成员变量,接收搜索子线程的句柄
{
WaitForSingleObject(m_hSearchThread, INFINITE);
m_hSearchThread = NULL;
} CSearchProcess *pSearchProcess = new CSearchProcess(this, strSearchTxt);
CWinThread *pWinThread = AfxBeginThread(SearchResourceProc, static_cast<LPVOID>(pSearchProcess));
if (pWinThread)
{
m_hSearchThread = pWinThread->m_hThread;
}
}
//这个函数是一个按钮的响应函数,负责停止搜索过程
void CResourceDlg::OnBnClickedBtnClose()
{
// TODO: Add your control notification handler code here
NormalState();//把状态改成非搜索模式,这样,子线程里面就可以知道要退出搜索了
if (m_hSearchThread)
{
DWORD dwRet = WaitForSingleObject(m_hSearchThread, INFINITE);//这里就死掉了
ASSERT(dwRet == WAIT_OBJECT_0);
m_hSearchThread = NULL;
}
}
线程的函数代码可以确定是正确的。因为不点这个停止搜索按钮的时候,是可以正常搜索的。可是一点停止搜索,就死锁了。
因为你已经验证了等待那个线程句柄是不行的了。
其实是这么一个模式:
主线程中的这个搜索按钮点击后,生成一个搜索资源的子线程,而这个子线程要把结果写到一个控件上,这个控件是属于主线程的,只不过子线程中得到了它的指针,从而可以往它上面加东西。
因此,在主线程中,如果点击停止搜索的按钮,像我代码中的那样,等待子线程的结束,从而主线程进入等待状态。此时,子线程获得CPU,但它要把搜索结果写到主线程上的控件中,由于主线程已经陷入等待状态,所以这个过程无法完成,反而让子线程也进入到等待状态了。这样就出现死锁了。我发现考虑用个事件内核对象也不太好解决问题呢,各位有什么好的办法吗?
改成postmessage来写吧.
数据可以作成全局的,PostMessage只做简单通知.
不要在主线程中WaitForSingleObject()
一旦我输入某个关键字如“北京”,那么就要进行搜索,把搜索结果显示在这个CListCtrl中。同时,还可以随时停止搜索动作。而且,最好是我搜索的时候如果再次输入关键字,搜索过程能够放弃刚才正在做的搜索过程而开始重新搜索。
部长说的采用子线程发送消息过来,我也想过,可是这个办法不好解决这样一个问题:我在搜索的时候,搜索还没结束,可点了停止搜索按钮,还是无法立刻停止子线程的搜索过程。除非在主线程中采用死循环不断判断子线程传回来的状态信息。
那主线程就根本不需要等待工作线程结束。而按LZ自己的说法工作线程
中又在调用主线程的控件即需要主线程控件的响应,所以导致死锁。可以试试换一种方式,在工作线程的末尾向主线程发送一个异步消息
(PostMessage),主线程在这个消息中做后续处理。如果这样还不行,
I'm afraid 你只能是再开一个监视线程了。另外,我不太明白你为什么不能直接杀线程(TerminateThread)。
如果正确的找到了,就发送消息到主进程。总之,更改界面的操作都要放在主进程的消息处理里面,否则容易混乱。
还可以加个定时器,规定时间内没有找到,定时的kill线程。具体是terminate,还是个什么玩意,你查吧。
别忘记killtimer。