我在一对话框起动时创建了一个线程,线程功能是:间隔25毫秒从5050端口接收广播来的数据,我在对话框的WM_DESTORY中使用了CEvent进行等待线程退出。但在退出时,有时事整个程序都没有了响应,主要原因是不知道该线程何时结束。
分不够可再加,如果谁要代码参考,可留个EmailBOOL CDlgServer::OnInitDialog() 
{......
m_event.ResetEvent();m_event2.ResetEvent();
AfxBeginThread((AFX_THREADPROC)ThreadFun,this);

void CDlgServer::OnDestroy() 
{
        CDialog::OnDestroy();
// TODO: Add your message handler code here
m_event.SetEvent();
WaitForSingleObject(m_event2,INFINITE/*无限等待*/);
TRACE("CDlgServer类完整的安全退出\n");
}
UINT __stdcall  CDlgServer::ThreadFun(LPVOID lp)
{
CDlgServer* pDlg=(CDlgServer*)lp;
sockaddr_in from,a;
BOOL optval=TRUE;int result=0;CString str;
a.sin_family=AF_INET;
a.sin_addr.s_addr=0;
a.sin_port= htons(5050) ; from.sin_family=AF_INET;
from.sin_addr.s_addr=INADDR_BROADCAST;
from.sin_port=htons(5050); int fromlength=sizeof(SOCKADDR);
//用UDP初始化套接字
pDlg->m_socket=socket(AF_INET,SOCK_DGRAM,0);
if(pDlg->m_socket == INVALID_SOCKET)
{
pDlg->m_socket = -1;
pDlg->m_event2.SetEvent();
TRACE("初始化失败(%d)\n",result);
return 0;
} optval=25;//设置接收超时为25毫秒
result = setsockopt(pDlg->m_socket,SOL_SOCKET,SO_RCVTIMEO,(char*)&optval,sizeof(optval));
if(result == SOCKET_ERROR)
{
closesocket(pDlg->m_socket);pDlg->m_socket = -1;
pDlg->m_event2.SetEvent();
TRACE("设置接收超时失败(%d)\n",result);
return 0;
} //设置该套接字为广播类型,
optval = TRUE;
result = setsockopt(pDlg->m_socket,SOL_SOCKET,SO_BROADCAST,(char FAR *)&optval,sizeof(optval));
if(result == SOCKET_ERROR)
{
closesocket(pDlg->m_socket);pDlg->m_socket = -1;
pDlg->m_event2.SetEvent();
TRACE("设置广播类型失败(%d)\n",result);
return 0;
} result = bind(pDlg->m_socket,(struct sockaddr *)&a,sizeof(sockaddr_in));
if(result == SOCKET_ERROR)
{
closesocket(pDlg->m_socket);pDlg->m_socket = -1;
pDlg->m_event2.SetEvent();
TRACE("帮定失败(%d)\n",result);
return 0;
}
SERVERSTRUCT ss;
result = 0;fromlength = sizeof(from);
while(1)
{//从广播地址接收消息,注意用来绑定的地址和接收消息的地址是不一样的10060
result = WaitForSingleObject(pDlg->m_event,25);
        if(result != WAIT_TIMEOUT)
break;
TRACE("没有WaitForSingleObject(%d)\n",result);
ZeroMemory((char*)&ss,sizeof(SERVERSTRUCT));
result = recvfrom(pDlg->m_socket,(char*)&ss,sizeof(SERVERSTRUCT),0,(struct sockaddr FAR *)&from,(int FAR *)&fromlength);
if(result == (int)sizeof(SERVERSTRUCT))
{   ....对数据进行处理 
}//end if
}//end while(1)
    closesocket(pDlg->m_socket);pDlg->m_socket = -1;
TRACE("线程CDlgServer::ThreadFun安全退出\n");
pDlg->m_event2.SetEvent();
return 0;
}

解决方案 »

  1.   

    线程中可以设置事件来退出。
    m_hQuitEvent = CreateEvent( NULL, FALSE, FALSE, TEXT("CComposeImage_Quit"));
    if( !m_hQuitEvent )
        {
            AfxMessageBox("CreateEvent failed!");
    return;
        }线程中加入
     DWORD rc = WaitForSingleObject(m_hQuitEvent, (DWORD)1);
            if (rc == WAIT_OBJECT_0) 
    {
                break;
            }
    需要退出时:            SetEvent(m_hQuitEvent);
                WaitForSingleObject(m_hThread, INFINITE); 
                CloseHandle(m_hThread);
      

  2.   

    有意思,能给我看代码吗
    [email protected]
      

  3.   

    [email protected]
    我帮你看看!
      

  4.   

    首先不要用while(1) 改成 while(bSwichtOn) 系统初始化时bSwichtOn =TRUE ,
    试图关闭线程时首先bSwichtOn =FALSE ;然后关闭接受套节子,使得recvfrom函数出错,线程可以安然退出.
    这招比较惯用,你试一试吧!
      

  5.   

    同楼上.补充:bSwichtOn不要是线程的局部变量,最好是对话框传过来的bool变量的指针pSwitchtOn.
    代码变为while(*pSwitchtOn).这种方法比不上用事件来得安全,但优点是:简单.
      

  6.   

    搞一个全局变量bThreadEnd,初始化为false,线程退出时置为true
    在Destory中检测等待。