我在一对话框起动时创建了一个线程,线程功能是:间隔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;
}
分不够可再加,如果谁要代码参考,可留个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;
}
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);
[email protected]
我帮你看看!
试图关闭线程时首先bSwichtOn =FALSE ;然后关闭接受套节子,使得recvfrom函数出错,线程可以安然退出.
这招比较惯用,你试一试吧!
代码变为while(*pSwitchtOn).这种方法比不上用事件来得安全,但优点是:简单.
在Destory中检测等待。