m_hThread = CreateThread(NULL, 0, m_pThreadFunction, this, dwCreationFlags, &dwCreationFlags);这段代码在堆上运行没有问题,但是在栈里面运行 m_hThread为NULL,谁知道为什么?
int _tmain(int argc,char *argv[],char *envp[])
{
CSocketThread *threadone = new CSocketThread();
threadone->Start();
CSocketThread threadtwo;
threadtwo.Start(0);
system("pause");
return 0;
}
是否是生存期的问题?
int _tmain(int argc,char *argv[],char *envp[])
{
CSocketThread *threadone = new CSocketThread();
threadone->Start();
CSocketThread threadtwo;
threadtwo.Start(0);
system("pause");
return 0;
}
是否是生存期的问题?
与 CSocketThread threadtwo;
以我的理解来看,这个跟堆和栈上创建线程没有什么关系。只是你的CSocketThread对象的存储是在栈还是堆上,真正线程创建后还是在当前进程的地址空间内由进程统一管理,你的线程创建后并不属于任何一个CSocketThread对象,CSocketThread对象只扮演了一个线程创建者的身份而已,一旦创建后,在堆上和在栈上创建的线程没有任何区别。线程的堆栈地址空间仍然是由系统从当前进程的地址空间分配的。
其实类似于CreateThread这类的函数很少会出现返回NULL,就是说创建线程不成功的情况。多贴点代码出来或者自己进一步用GetLastError看看错误代码。
尽量用AfxBeginThread或_beginthreadx,尽量别用CreateThread。
对ErrorNo值的影响是CreateThread最明显的弊端。
而且我昨天蛮去测试了一下,发现栈上Create出来的线程有时候也能运行,只是概率比较低。
#include "stdio.h"
#include "stdlib.h"
#include <iostream>
using namespace std;#include "winsock2.h"
#include "BaseThread.h"
//#pragma (lib,"ws2_32.lib")//=============================== Type Part ====================================class CSocketThread:public CBaseThread
{
protected:
//子类必须实现,线程的具体方法
DWORD ThreadMethod()
{
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n"); //----------------------
// Create a SOCKET for connecting to server
m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (m_hSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
WSACleanup();
return FALSE;
} //----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sockaddr_in clientService;
clientService.sin_family = AF_INET;
// clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
clientService.sin_addr.s_addr = inet_addr( "192.168.18.67" );
// clientService.sin_addr.s_addr = inget_addr( "218.234.70.58" );
clientService.sin_port = htons( 60000 );
// clientService.sin_port = htons( 8090 ); //----------------------
// Connect to server.
if ( connect( m_hSocket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) {
printf( "Failed to connect.\n" );
WSACleanup();
return FALSE;
} //----------------------
// Declare and initialize variables.
int bytesSent;
int bytesRecv = 0;
char sendbuf[32] = "Client: Sending data.";
char recvbuf[32] = ""; //----------------------
// Send and receive data.
bytesSent = send( m_hSocket, sendbuf, strlen(sendbuf), 0 );
printf( "Bytes Sent: %ld\n", bytesSent ); while( bytesRecv != SOCKET_ERROR )
{
bytesRecv = recv( m_hSocket, recvbuf, 32, 0 );
DWORD dwError = GetLastError();
if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET )
{
printf( "Connection Closed.\n");
break;
}
printf( "Bytes Recv: %ld\n %s\n", bytesRecv ,recvbuf );
} WSACleanup();
return TRUE;
}
private:
SOCKET m_hSocket;
};//==============================================================================//=============================== Function Part ================================void ThreadCreateOnStack()
{
WORD flag = 0;
CSocketThread testThread;
testThread.Start(flag);
int iRet = testThread.GetPriority();
testThread.Resume();
}
void ThreadCreateOnHeap()
{
WORD flag = 0;
CSocketThread *pTestThread = new CSocketThread();
pTestThread->Start(flag);
}int _tmain(int argc,char *argv[],char *envp[])
{
ThreadCreateOnStack();
// ThreadCreateOnHeap();
system("pause");
return 0;
}
//==============================================================================
//////////////////////////////// End of File //////////////////////////////////
//=============================== Type Part ==================================//class CBaseThread
{
public:
/** Constructor */
CBaseThread();
/** Destructor */
~CBaseThread();
public:
// 设置优先级
BOOL SetPriority(int priority);
// 获取优先级
int GetPriority();
// 挂起线程
DWORD Suspend();
// 还原线程
DWORD Resume();
// 开始跑
DWORD Start(DWORD dwCreationFlags = 0);
// 停止
DWORD Stop ( bool bForceKill = false);
DWORD Stop ( WORD timeout );protected:
//子类必须实现,线程的具体方法
virtual DWORD ThreadMethod() = 0;
private:
//
static DWORD WINAPI CBaseThread::EntryPoint( LPVOID pArg);protected:
LPTHREAD_START_ROUTINE m_pThreadFunction; //工作线程指针
BOOL m_bRunThread; //线程是否继续运行的标志
private:
HANDLE m_hThread; //Thread Handle 线程句柄
DWORD m_dwThreadID; //Thread ID 线程ID
LPVOID m_pParent; //pointer of the parent CThread object
DWORD m_dwExitCode; //Exit Code of the thread 线程退出码
};
//============================================================================////////////////////////////////// End of File ///////////////////////////////////#include "BaseThread.h"//------------------------------------------------------------------------------
// Method: CBaseThread
// Returns:
// Access: public
// Functionality: 构造函数
// Author : Vken.Chen
//------------------------------------------------------------------------------
CBaseThread::CBaseThread()
{
m_pThreadFunction = CBaseThread::EntryPoint;
m_bRunThread = FALSE;
}
//------------------------------------------------------------------------------
// Method: ~CBaseThread
// Returns:
// Access: virtual public
// Functionality: 析构函数
// Author : Vken.Chen
//------------------------------------------------------------------------------
CBaseThread::~CBaseThread()
{
if ( m_hThread )
Stop(true); //thread still running, so force the thread to stop!
}//------------------------------------------------------------------------------
// Method: EntryPoint
// Returns: DWORD WINAPI
// Access: public static
// Parameter: LPVOID pArg
/* Functionality: DONT override this method.
this method is the "function" used when creating the thread. it is static so that way
a pointer to it is available inside the class. this method calls then the virtual
method of the parent class.
*/
// Author : Vken.Chen
//------------------------------------------------------------------------------
DWORD WINAPI CBaseThread::EntryPoint( LPVOID pArg)
{
CBaseThread *pParent = reinterpret_cast<CBaseThread*>(pArg);
pParent->ThreadMethod();//多态性,调用子类的实际工作函数
return 0;
}//------------------------------------------------------------------------------
// Method: Start
// Returns: DWORD
// Access: public
// Parameter: DWORD dwCreationFlags,the flags to use for creating the thread.
// see CreateThread() in the windows sdk.
// Functionality: Starts the thread
// Author : Vken.Chen
//------------------------------------------------------------------------------
DWORD CBaseThread::Start(DWORD dwCreationFlags)
{
m_bRunThread = true;
m_hThread = CreateThread(NULL, 0, m_pThreadFunction, this, dwCreationFlags, &dwCreationFlags);
m_dwExitCode = GetLastError();
return m_dwExitCode;
}
void ThreadCreateOnStack()
{
WORD flag = 0;
CSocketThread testThread;
testThread.Start(flag);
int iRet = testThread.GetPriority();
testThread.Resume();
}
thread运行之后,testThread对象已经被销毁了,所以线程丢失了自己的地址空间,因为你的线程函数是依赖于类地址空间的,它的地址是在类地址空间的某处。不知道是否是这个问题引起的,但从当前情况来看,是的。