)::WaitForSingleObject

来源:互联网 发布:阿里云服务器使用手册 编辑:程序博客网 时间:2024/05/20 17:27

转自  http://topic.csdn.net/u/20071011/22/b3e17e2d-b6ca-4484-9e19-7354e47ea10c.html

 

主要学习到两点:

1)::WaitForSingleObject(m_hThread,INFINITE);
    主要功能同志 线程m_hThread句柄 有消息了(相当于信号量),第二个参数表示死等

 

2)不建议此接口用在主线程。

 

3)对话框的头文件中:
#define   YOURMESSAGE   WM_USER   +1

在//}}AFX——
与DECLARE——MESSAGE——MAP()
之间加上
afx_msg   LRESULT   OnYourMessage(WPARAM   wParam   ,LPARAM   lParam);

然后在CPP中:
在BEGIN——MESSAGE_MAP()
中的//}}AFX_MSG_MAP
与EMD_MESSAGE_MAP()之间加上
ON_MESSAGE(YOURMESSAGE,OnYourMessage)
然后定义OnYourMessage()

然后就可以在你的线程中POSTMESSAGE()了


 

我做了如下的一个小实验程序:
在VC中创建一个MFC对话框工程Test,添加两个按钮IDC_BUTTON_CREATE_THREAD和IDC_BUTTON_EXIT_THREAD,分别用来控制创建子线程和结束子线程。它们的响应函数如下:
void CTestDlg::OnButtonCreateThread() 
{
// TODO: Add your control notification handler code here
DWORD dwThreadId = 0;
if (m_hThread == NULL)
{
m_hThread = ::CreateThread(0,0,ThreadProc,LPVOID(this),0,&dwThreadId);
}
}

void CTestDlg::OnButtonExitThread() 
{
// TODO: Add your control notification handler code here
if (m_hThread != NULL)
{
// Set the flag that the thread must be stopped
m_bThreadStopping = TRUE;

// Wait until the watcher thread has stopped
::WaitForSingleObject(m_hThread,INFINITE);

// The thread has stopped
m_bThreadStopping = FALSE;

// Close handle to the thread
::CloseHandle(m_hThread);
m_hThread = 0;
}
}
上面的代码中m_hThread是保存子线程句柄的CTestDlg成员变量,m_bThreadStopping是CTestDlg的静态成员变量,用来指示子线程退出。子线程的代码如下:
DWORD WINAPI CTestDlg::ThreadProc( LPVOID lpParameter )
{
LARGE_INTEGER nStartCount, nCurCount;

while (!m_bThreadStopping)
{
::QueryPerformanceCounter(&nStartCount);
do
{
::QueryPerformanceCounter(&nCurCount);
} while (nCurCount.QuadPart < nStartCount.QuadPart + 1000);
if (!m_bThreadStopping)
{
::SendMessage(((CTestDlg *)lpParameter)->GetSafeHwnd(), WM_APP+1, 0, 0);
}
}
return 999;
}
子线程是CTestDlg的静态成员函数,它的功能实际是每隔一定时间向主线程(UI线程)发送消息,相当于一个定时器。为达到准确的时间控制,消息发送用了SendMessage(),而不是PostMessage()。主线程中的消息响应如下:
LRESULT CTestDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
// TODO: Add your specialized code here and/or call the base class
static UINT uCount = 0;
if (message == WM_APP + 1)
{
SetDlgItemInt(IDC_STATIC, uCount, FALSE);
uCount++;
}
else
{
return CDialog::WindowProc(message, wParam, lParam);
}
}
就是在IDC_STATIC静态文本控件中显示接收到子线程消息的次数。

问题就在于,有的时候当点击“结束线程”(也就是IDC_BUTTON_EXIT_THREAD按钮)时,程序再不响应用户操作,但静态文本控件中的计数值不变,疑似进入死锁状态。当子线程发送消息的间隔时间缩短时,这种现象更严重。我怀疑有可能是下面的情况发生了,就是主线程在等待子线程结束的时候被挂起(在执行WaitForSingleObject()时),但是子线程同时又在等待主线程返回消息处理结果(即子线程正在执行SendMessage())。但是我又觉得在子线程正在执行SendMessage()函数时,主线程应该不会响应用户点击“结束线程”的事件才是,因为SendMessage()发送的消息是Non-queued消息,而点击“结束线程”的消息是queued消息,它被放在消息队列中,至少应该等到子线程的SendMessage()调用主线程窗口的WindowProc()处理完子线程发送的消息之后才会被处理。这样说来,上面的死锁情形就不应该发生。想了一整天没弄明白为什么会发生这种现象,还望高手指点,在此先谢谢了!

原创粉丝点击