Sign in to follow this  
adriano_usp

[C++] Best way to create and end threads

Recommended Posts

Hi, I tring to find a good way to externally end a thread. Please, consider the following code (very simple):
class CL_THREAD
{
public:
  CL_THREAD();
  ~CL_THREAD();	            
	
private:

  HANDLE thHandle;

  static void threadFunc(void *arg)
  {
    ...

     _endthread();			
  }

};

CL_THREAD::CL_THREAD()
{
  thHandle = (HANDLE) _beginthread( threadFunc, 0, NULL );
			
  if(!thHandle) 
    MessageBox(0,"_beginthread failed.",0,0);
}

CL_THREAD::~CL_THREAD()
{
  ::TerminateThread(thHandle,0);			
}

The TerminateThread() function could be dangerous in some cases. So, I'm searching a better way to end threads. Please, could anybody help me? Thanks in advance.

Share this post


Link to post
Share on other sites
The best way to terminate a thread is by returning from the thread function you pass into _beginthread. Your call to _endthread at the end of your thread function is redundant, because it will be called when the thread returns from that function anyways.

Share this post


Link to post
Share on other sites


volatile bool running = true;

void threadFunc()
{
while (running) {

// do the thread stuff
}
}

....

// when done with thread
running = false;



This is one way to do it.

Share this post


Link to post
Share on other sites
First I just set the "bool can_run" flag to false, in hopes that the thread terminates on its own,
done in my "stop" function.
This is followed by my calling thread running "join" to wait for the thread to finish.

I also have a "forcejoin" that waits a specified time for the thread to terminate then calls terminatethread.

And in my destructor, I set can_run to false. and forcejoin with a default timer.

Share this post


Link to post
Share on other sites
Thanks friends. I rewrote the code to make the thread returns:


class CL_THREAD
{
public:
CL_THREAD();
~CL_THREAD();

private:

bool terminate;
HANDLE thHandle;

static void threadFunc(void *arg)
{
CL_THREAD *p = (CL_THREAD*)arg;
p->Func();
}

void Func()
{
while(terminate == false)
{
...
}
}
};

CL_THREAD::CL_THREAD()
{
terminate = false;
thHandle = (HANDLE) _beginthread( threadFunc, 0, NULL );

if(!thHandle)
MessageBox(0,"_beginthread failed.",0,0);
}

CL_THREAD::~CL_THREAD()
{
terminate = true;
}




So, the thread is terminated by calling the destructor. But... is there no way to instantly terminate the thread without using TerminateThread()? That is, without waiting the while loop be completed.

Thanks in advance

Share this post


Link to post
Share on other sites
Quote:
Original post by adriano_usp
Thanks friends. I rewrote the code to make the thread returns:

*** Source Snippet Removed ***

So, the thread is terminated by calling the destructor. But... is there no way to instantly terminate the thread without using TerminateThread()? That is, without waiting the while loop be completed.

Thanks in advance


Ouch on several levels.

First, you never call destructor, unless you're doing your own custom new overloaded memory allocation.

Second, calling delete X will destroy the object and its resources, but the thread will keep on running. By the time it gets to check the flag, the location of that flag may be who knows where.

Forcing thread termination is not possible in many libraries, or is strongly discouraged in others. There's plenty of reasons for that, but terminating a thread while it's running is generally considered as: Do Not Do It (tm).

Here's one way, if you insist on wrapping the classes:

class Thread {

Thread()
: running( true )
, completed( false )
{
// start thread by passing run() as its function
}

// override this to implement what the thread should do
virtual void threadFunc() = 0;

void stopThread( int timeout_ms )
{
// poll for completion every 25 ms to avoid hogging down the CPU
int granularity = 25;
timeout_ms /= granularity;
int i = 0;

// Signal thread to stop running
running = false;

// Wait for thread to complete
while (!completed && (i < timeout_ms ) ) {
Sleep(granularity);
i += granularity;
}

// If thread didn't complete, we have a problem
if (!completed) throw std::exception("Failed to stop the thread");
}
private:
void run()
{
while ( running ) {
threadFunc();
}
// Once requested to exit, signal that we're done
completed = true;
}

volatile bool running;
volatile bool completed;
}



Note that this isn't a working example.

The virtual function is there only as a place holder, you can't really do that.

The whole demonstration serves merely to show how to wait for a thread to finish. You cannot force a thread to stop, and you really do not know if the thread will stop when requested.

This is what concurrent/asynchronous programming brings along. And it's a Bad Idea(tm) to fight against these mechanisms. There are far too many problems that they bring about.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
The whole demonstration serves merely to show how to wait for a thread to finish.


IMO the right way to wait for a thread to terminate is to use the WaitForSingleObject API.

A very simple example:


struct ThreadBase
{
static DWORD WINAPI ThreadEntry(void* pThreadClass)
{
return ((ThreadBase*)pThreadClass)->Main(); // You can use a better, safer cast.
}

virtual DWORD Main() = 0;

void Create()
{
CreateThread(NULL, 0, ThreadEntry, this, CREATE_SUSPENDED, &threadID);
}

// ----------------------------

void Start()
{
ResumeThread(threadID);
}

// ----------------------------

// /!\ CALLING THIS FROM THE THREAD YOU'RE TRYING TO END WILL DEADLOCK :)

void Stop()
{
keepRunning = false; // May want to use a InterlockXXX method, and/or to declare keepRunning volatile

// optionnaly wait for the thread to terminate, you can even set a timeout
WaitForSingleObject(m.threadID, 0xFFFFFFFF);

}

DWORD threadID;
bool keepRunning; // Subclasses are responsible for checking this value.

}

struct SomeModule : public ThreadBase
{
virtual DWORD Main()
{
while(keepRunning)
{
/* Do whatever */
}
return 0; // or whatever error code or anything you wish.
}
}

int main()
{
SomeModule m;
m.Create();
m.Start();

bool appRunning = true;

while(appRunning)
{
/* Do whatever */
}

m.Stop();
}






And it's better (recomanded by microsoft) to use the _beginthread/etc. methods just as you did.

[Edited by - janta on May 4, 2007 2:32:28 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this