VC线程的退出检测

以前一直在用线程,这两天又搞了一个线程用在一个小工具上,发现每次退出时总是卡住导致无响应只好强行关闭它。原以为是在目标电脑上有这个问题,结果今天在自己的电脑上也出现了,而且是必现,不过只在release下必现,而debug下没有出现过这个情况。


这个工具是个udp服务器,用来测试其它udp广播功能的。在启动之后,会创建一个线程,这个线程中不断地接收udp数据,如果接收到了就进行界面显示。大致的代码如下:

void DataRecvRoutine()
{
	TCHAR szMsg[128];
	_stprintf( szMsg, TEXT("udp server %d running~~~\n"), m_threadid );
	OutputDebugString( szMsg );

	int iret = 0;
	int err = 0;
	int iAddrLen = sizeof(sockaddr);
	while ( m_bRunning )
	{
		err = 0;
		iAddrLen = sizeof(sockaddr_in);
		memset( m_pbuffer, 0, m_lBufferLen );
		iret = recvfrom( m_socket, m_pbuffer, m_lBufferLen, 0, (sockaddr*)&gsckaddr_server, &iAddrLen );
		if ( iret == SOCKET_ERROR )
		{
			err = WSAGetLastError();
			break;
		}

		// 显示接收到的数据
		CBRecData( m_pbuffer, iret );
	}

	// 恢复各状态变量
	Sleep( 100 );
	if ( m_socket != -1 )
	{
		closesocket( m_socket );
		m_socket 	= -1;
	}
	_stprintf( szMsg, TEXT("udp server %d stopped ~~~\n"), m_threadid );
	OutputDebugString( szMsg );
	m_threadid = 0;
	m_bRunning = false;
	CloseHandle( m_hthread );
	m_hthread = NULL;  // 关闭线程句柄,使检测者可以进行检测
}


注意此线程函数,在退出时,会把它的线程句柄m_hthread关闭并置为NULL。在停止服务器的接口中,代码大致如下:

UINT32 StopServer()
{
	if ( !m_bRunning )
	{
		return RME_OTHER_TASKNOTGO;
	}
	
	m_bRunning = false;

	// 关闭soket,使接收函数返回-1从而退出while循环
	if ( m_socket != -1 )
	{
		closesocket( m_socket );
		m_socket 	= -1;
	}

	while ( m_hthread );	Sleep( 100 );

	return RME_SUCCESS;
}

这个退出用m_hthread进行不断地检测,直到为NULL时退出然后返回。通过打印看,线程DataRecvRoutine()已经退出了,而且

_stprintf( szMsg, TEXT("udp server %d stopped ~~~\n"), m_threadid );

这一行的打印也出来了,后来在这个函数的最后一行加了打印,也有打印出来,这里看,就只有这个退出检测的while循环一直没有退出了。这个情况只在release下必现,在debug下从来没有出现过。我用的是vs2008编译。

后来为了解决这个问题,把这个退出检测改为正常的检测,使用事件进行检测,如下修改:

	//while ( m_hthread );	Sleep( 100 );
	::WaitForSingleObject( m_hthread, 10000 );

然后测试正常了。

在写这篇文章时,发现了在while(m_hthread)后面多写了个分号;,属于笔误,然后再进行修改:

	while ( m_hthread )	Sleep( 100 );
	//::WaitForSingleObject( m_hthread, 10000 );

再测试也正常了。


大致有如下的结论。release编译时会对空的循环进行优化操作,其导致了不该出现的问题。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值