51代码网ORACLEMYSQLSQL SERVER其它数据库java/jspasp/asp.netC/C++/VC++APP应用其它语言服务器应用
您现在的位置: 51代码网 >> C >> 文章正文

createthread()函数传递指针失败

更新时间:2012-2-26:  来源:51代码网

主线程负责初始化SOCKET,完成后,另开辟一线程,用于监听和接收连接请求,接受连接请求后,再创建一个线程用于通信(收发信息)。

现在的问题是,定义了一个传参的结构体,然后在主线程中声明结构体变量指针,给需要传递的结构体项赋值,然后向监听线程传参。这步没问题。

但是在监听线程中和主线程中一样,同样声明结构体变量指针,然后赋值,通过createthread()函数向通信线程传递指针时,怎么也传不过去。

代码大致如下:

主线程中的传递指针部分:
//定义一个向线程里传参的结构体指针,并初始化
  //结构体RecvParam里有两项,一个是HWND类型,一个是SOCKET类型
RecvParam *pRecvP = new RecvParam ;
pRecvP->sock = sock_Listen ;
pRecvP->hwnd = m_hWnd ;
  //测试指针传递
CString test ;
test.AppendFormat(_T("%d"),pRecvP->sock) ;
AfxMessageBox(test) ;
//创建线程并立即执行接受TCP连接请求的函数RecvConProc()
  HANDLE hThread = CreateThread( NULL,0,ListenProc,(LPVOID)pRecvP,0,NULL ) ; CloseHandle( hThread ) ; //关闭句柄
监听线程:
// 函数用于接受客户的TCP连接请求
DWORD CChattingRoom_SrvDlg::ListenProc(LPVOID lpParam)
{
SOCKET sock1 = ((RecvParam*)lpParam)->sock ;
CSockApp csock ; //CSockApp是自己写的执行SOCKET操作的类

  //测试指针传递
CString test ;
test.AppendFormat(_T("%d"),sock1) ;
AfxMessageBox(test) ;

  //
RecvParam* rParam = new RecvParam ;
rParam = (RecvParam*)lpParam ;

test.Format(_T("%d"),rParam->sock) ;
AfxMessageBox(test) ;

sockaddr_in cliAddr ;
int len = sizeof(SOCKADDR) ;
//监听
if( 0 == csock.SockListen(sock1) )
return 0;
SOCKET clisock = INVALID_SOCKET;
int nCliCount = 0 ; //计数器,用于统计客户端数
HANDLE hNewThread = NULL ;
while(1)
{
clisock = csock.SockAccept(sock1,&cliAddr) ; //执行accept()函数
rParam->sock = clisock ;
test.Format(_T("%d"),rParam->sock) ;
AfxMessageBox(test) ;
if( INVALID_SOCKET != rParam->sock )
{
++nCliCount ;
hNewThread = CreateThread(NULL,0,RecvProc,(LPVOID)rParam,0,NULL) ;
CloseHandle(hNewThread) ;
rParam->sock = INVALID_SOCKET ;
}
}
delete lpParam ;
return 0;
}
通信线程:

DWORD CChattingRoom_SrvDlg::RecvProc(LPVOID lpParam)
{
  //声明一个结构体指针用于存储传递过来的变量
RecvParam* getParam = new RecvParam ;
getParam = (RecvParam*)lpParam ;

//测试指针传递:就是在这里测试出指针传递失败
CString test ;
test.Format(_T("%d"),((RecvParam*)lpParam)->sock) ;
AfxMessageBox(test) ;

  //CChattingRoom_SrvDlg是对话框类
CChattingRoom_SrvDlg cdlg ;
  //用于执行SOCKET编程的类
CSockApp sockRecv;
cdlg.m_hWnd = getParam->hwnd ;

SOCKET recvsock = getParam->sock ;
CString csTmpMsg = NULL ;
int nretval = 1 ;
char buff[20] ;
while(nretval)
{
memset(buff,0,20) ;
nretval=sockRecv.SockRecv(recvsock,buff); //接收信息
if( 0 >= nretval )
{
cdlg.GetDlgItemText(IDC_EDIT_CONTENT,csTmpMsg) ;
csTmpMsg.Append(_T("\n连接断开!"));
//AfxMessageBox(_T("111")) ;
cdlg.SetDlgItemText(IDC_EDIT_CONTENT,csTmpMsg) ;
break;
}
else
{
cdlg.GetDlgItemText(IDC_EDIT_CONTENT,csTmpMsg) ;
//AfxMessageBox(_T("222")) ;
csTmpMsg.Append(_T(buff));
cdlg.SetDlgItemText(IDC_EDIT_CONTENT,csTmpMsg) ;
}
}
return 0;
}
请问我的代码哪里有错?想了很久也没想明白。为什么向通信线程传递指针会失败呢?

原因是不是CloseHandle(hNewThread) ;已经结束了线程
确实是线程关闭了。
还想请问的是,closehandle()这个函数到底是怎么用的?
因为看孙鑫的C++视频里是创建线程之后就关闭了CreateThread函数开启线程,反回了线程的HANDLE。如果程序中不需要用到该线程的句柄,就可以使用CloseHandle将线程句柄释放。CloseHandle只是将句柄释放,并未将线程关闭。

  • 上一篇文章:
  • 下一篇文章: 没有了
  • 赞助商链接
    推荐文章
  • 此栏目下没有推荐文章
  • {
    设为首页 | 加入收藏 | 友情链接 | 网站地图 | 联系站长 |