关于_endthread()后函数栈的析构

飞翔的土豆 2010-02-25 05:23:03
MSDN上说:
“however, _endthread or _endthreadex is called automatically when the thread returns from the routine passed as a parameter to _beginthread or _beginthreadex. Terminating a thread with a call to endthread or _endthreadex helps to ensure proper recovery of resources allocated for the thread.”

那么如果我显式调用了_endthread后,当前函数还能否返回时正常析构吗?貌似_endthread后面的语句都不执行了~~
求高人解释,最好能给出线程主动退出时的一般做法~
...全文
272 7 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
stjay 2010-02-25
  • 打赏
  • 举报
回复
_endthread后线程都终结了,后面的语句就不会执行了
最好的线程主动退出时的一般做法 就是直接return;

#include <Windows.h>
#include <process.h>
#include <iostream>
#include <list>
using namespace std;

class CMyClass
{
public:
CMyClass()
{
cout<<"Default constructor"<<endl;
}
CMyClass(const CMyClass& obj)
{
cout<<"Copy constructor"<<endl;
}
~CMyClass()
{
cout<<"Destructor"<<endl;
}
};
void ThreadFunc(LPVOID lParam)
{
if(lParam==NULL)
{
return;
}
CMyClass myobj;
// _endthread();
}
void main()
{
_beginthread(ThreadFunc,0,NULL);
char c;
cin>>c;
}
飞翔的土豆 2010-02-25
  • 打赏
  • 举报
回复
事实证明:函数栈回收时不析构。。简单写了个程序如下:

#include <Windows.h>
#include <process.h>
#include <iostream>
#include <list>
using namespace std;

class CMyClass
{
public:
CMyClass()
{
cout<<"Default constructor"<<endl;
}
CMyClass(const CMyClass& obj)
{
cout<<"Copy constructor"<<endl;
}
~CMyClass()
{
cout<<"Destructor"<<endl;
}
};
void ThreadFunc(LPVOID lParam)
{
CMyClass myobj;
// _endthread();
}
void main()
{
_beginthread(ThreadFunc,0,NULL);
char c;
cin>>c;
}

注释如果去掉的话,自定义的myobj没能析构。。
WizardK 2010-02-25
  • 打赏
  • 举报
回复
另一个_endthreadex和_beginthreadex的例子:
这个和_endthread的区别是需要你自己去关闭线程句柄,和ExitThread一样。


// crt_begthrdex.cpp
// compile with: /MT
#include <windows.h>
#include <stdio.h>
#include <process.h>

unsigned Counter;
unsigned __stdcall SecondThreadFunc( void* pArguments )
{
printf( "In second thread...\n" );

while ( Counter < 1000000 )
Counter++;

_endthreadex( 0 );
return 0;
}

int main()
{
HANDLE hThread;
unsigned threadID;

printf( "Creating second thread...\n" );

// Create the second thread.
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );

// Wait until second thread terminates. If you comment out the line
// below, Counter will not be correct because the thread has not
// terminated, and Counter most likely has not been incremented to
// 1000000 yet.
WaitForSingleObject( hThread, INFINITE );
printf( "Counter should be 1000000; it is-> %d\n", Counter );
// Destroy the thread object.
CloseHandle( hThread );
}
WizardK 2010-02-25
  • 打赏
  • 举报
回复
首先,_endthread和_beginthread配对使用
其次,能在线程内部调用_endthread,其后可以return。

看MSDN的例子:

// crt_BEGTHRD.C
// compile with: /MT /D "_X86_" /c
#include <windows.h>
#include <process.h> /* _beginthread, _endthread */
#include <stddef.h>
#include <stdlib.h>
#include <conio.h>

void Bounce( void *ch );
void CheckKey( void *dummy );

/* GetRandom returns a random integer between min and max. */
#define GetRandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))

BOOL repeat = TRUE; /* Global repeat flag and video variable */
HANDLE hStdOut; /* Handle for console window */
CONSOLE_SCREEN_BUFFER_INFO csbi; /* Console information structure */

int main()
{
CHAR ch = 'A';

hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );

/* Get display screen's text row and column information. */
GetConsoleScreenBufferInfo( hStdOut, &csbi );

/* Launch CheckKey thread to check for terminating keystroke. */
_beginthread( CheckKey, 0, NULL );

/* Loop until CheckKey terminates program. */
while( repeat )
{
/* On first loops, launch character threads. */
_beginthread( Bounce, 0, (void *) (ch++) );

/* Wait one second between loops. */
Sleep( 1000L );
}
}

/* CheckKey - Thread to wait for a keystroke, then clear repeat flag. */
void CheckKey( void *dummy )
{
_getch();
repeat = 0; /* _endthread implied */

}

/* Bounce - Thread to create and and control a colored letter that moves
* around on the screen.
*
* Params: ch - the letter to be moved
*/
void Bounce( void *ch )
{
/* Generate letter and color attribute from thread argument. */
char blankcell = 0x20;
char blockcell = (char) ch;
BOOL first = TRUE;
COORD oldcoord, newcoord;
DWORD result;


/* Seed random number generator and get initial location. */
srand( _threadid );
newcoord.X = GetRandom( 0, csbi.dwSize.X - 1 );
newcoord.Y = GetRandom( 0, csbi.dwSize.Y - 1 );
while( repeat )
{
/* Pause between loops. */
Sleep( 100L );

/* Blank out our old position on the screen, and draw new letter. */
if( first )
first = FALSE;
else
WriteConsoleOutputCharacter( hStdOut, &blankcell, 1, oldcoord, &result );
WriteConsoleOutputCharacter( hStdOut, &blockcell, 1, newcoord, &result );

/* Increment the coordinate for next placement of the block. */
oldcoord.X = newcoord.X;
oldcoord.Y = newcoord.Y;
newcoord.X += GetRandom( -1, 1 );
newcoord.Y += GetRandom( -1, 1 );

/* Correct placement (and beep) if about to go off the screen. */
if( newcoord.X < 0 )
newcoord.X = 1;
else if( newcoord.X == csbi.dwSize.X )
newcoord.X = csbi.dwSize.X - 2;
else if( newcoord.Y < 0 )
newcoord.Y = 1;
else if( newcoord.Y == csbi.dwSize.Y )
newcoord.Y = csbi.dwSize.Y - 2;

/* If not at a screen border, continue, otherwise beep. */
else
continue;
Beep( ((char) ch - 'A') * 100, 175 );
}
/* _endthread given to terminate */
_endthread();
}
飞翔的土豆 2010-02-25
  • 打赏
  • 举报
回复
引用 1 楼 wy2001wy 的回复:
函数怎么会有析构?
MSDN上说是是MFC里面分配的一些东西会被正常的释放,跟你自己的东西没有关系的。

函数在退出时,不是会对函数栈里的对象依次析构吗?我的意思是,如果在线程函数里显示调用_endthread,那么函数还会继续走下去吗(如果_endthread后面还有别的代码的话)?甚至能否return呢?
WizardK 2010-02-25
  • 打赏
  • 举报
回复
线程主动退出(起始最终还是被动)做法的一种:
要求线程退出时,SetEvent


HANDLE g_hEvent;

UINT THREADFUNC(...)
{
...

while (1)
{
if (WaitForSingleObject(g_hEvent, 0) == WAIT_OBJECT_0)
break;
...
}

return 0;
}
wy2001wy 2010-02-25
  • 打赏
  • 举报
回复
函数怎么会有析构?
MSDN上说是是MFC里面分配的一些东西会被正常的释放,跟你自己的东西没有关系的。

15,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧