Click here to Skip to main content
Licence 
First Posted 30 Jul 2005
Views 42,741
Bookmarked 23 times

CThread

By | 23 Aug 2005 | Article
CThread simplifies the process to start, run and stop threads. You can use it to work with threads in the same way as you do in C# or Java.

Introduction

CThread makes it possible to work with threads in MFC pretty much the same way as you do in C#/Java. You derive your own class from CThread and implement Run(void* ). To start the thread, you have to call Start(). Now a new thread starts it's execution in Run(). When Run() is finished, the thread stops its execution.

Using the code

To use the code you should derive your class from CThread. You must also implement the Run function, where the thread executes. Example:

class CMyThread : public CThread
{
    void Run(void* param);
}

It's OK if you want to derive from several classes, which is common if you want to run the thread in a dialog class:

class CMyThread : public CDialog, CThread
{
    void Run(void* param);
}

Starting the thread

Starting the thread is very simple, just call Start(). Now a new thread starts its execution in Run(). You should not call Start() if a thread is already running. To check this, call IsRunning().

You could send an optional parameter to the thread with a pointer. If you do this, make sure that the pointer is valid. The following example will not work:

{
    int parameter = 10;
    Start(&paramater);
}

When you call Start() the pointer is valid, but it may not always be so when the thread starts to execute. Use new instead:

{
    int* parameter = new int(10);
    Start(&paramater);
}

Don't forget to delete the object in Run(). The parameter is sent to the thread in Run() as a void pointer. You could also use member variables to send information to the thread.

Stopping the thread

To stop the thread, call Stop(). This will not stop the thread immediately; instead it sets a flag which tells the thread to stop its execution. If you want to wait for the thread to exit, call WaitForStop().

Running the thread

What the thread has to do is up to you. The thread will start its execution in Run(), the function that you must implement. When the thread exits Run(), it will finish its execution. When you implement Run(), you must check if the thread should stop its execution. This is true if some thread has called Stop(). To check the flag, call ShouldRun(). Example:

void CMyThread::Run(void* param)
{
    //Run the thread until someone has called Stop()
    while( ShouldRun() )
    {
        ...
    }
}

Sending messages from a thread

Very often you want to update the GUI from the thread. For example, you want to update a progress bar. The obvious solution is to update the progress bar directly from the thread. Example:

void CMyThreadInDialog::Run(void* param)
{
    ...
    m_progressbar.SetPos(10)
    ...
}

But this will not work. A golden rule in Windows is that only one thread should work with the GUI. Instead of this you should use messages. From the thread that is executing in Run() you should send a message to the main thread which tells the window to make the update. You should not use SendMessage, use PostMessage instead. SendMessage updates the GUI directly from the thread, which is not what you want. PostMessage adds a message to the window's messages queue and will be handled from the main thread.

So your code should look something like this:

void CMyThreadInDialog::Run(void* param)
{
    ...
    ::PostMessage(UPDATE_PROGRESSBAR, m_hWnd, 10, 0);
    ...
}

See the example for more details.

Points of interest

Before I wrote this class, I looked for something similar in CodeProject. To my surprise, I didn't find any article on this topic. But I wasn't looking hard enough... There are at last two articles that provide a similar solution:

  • CThread

    A more complex solution than my CThread (by the way, I'm sorry about the name conflict). But it's interesting to look at it.

  • AG_Thread

    This is a more simple solution than my CThread.

Even if I am not the first one to write an article on this topic, I hope someone finds this class useful :-).

History

  • 30th July, 2005 - Version 1.0. Initial version.
  • 21st August, 2005 - Version 1.01. Minor fixes and improvements suggested by Blake Miller.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

PEK



Sweden Sweden

Member

PEK is one of the millions of programmers that sometimes program so hard that he forgets how to sleep (this is especially true when he has more important things to do). He thinks that there are not enough donuts in the world. He likes when his programs works as they should do, but dislikes when his programs is more clever than he is.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralCThread and ISAPI Pinmemberluca9810:36 30 Aug '05  
GeneralRe: CThread and ISAPI PinmemberPEK8:36 30 Aug '05  
GeneralMore comments... PinmemberRolf Schaeuble3:49 23 Aug '05  
GeneralRe: More comments... PinmemberPEK8:46 30 Aug '05  
GeneralComments and Suggestions PinmemberBlake Miller10:50 1 Aug '05  
1. You probably could have used a critical section instead of a sempahore. You don't use it to wait on anything only to lock access to data - that's what critical sections do.
 
2. If m_thread is the pointer to the CWinThread, and they are set to auto delete by default, then you run the chance you will tell thread to stop, and before you can even check if it is stopped, the m_thread is deleted, but then you access it illegally in the WaitForStop - this is an access violation just waiting to happen.
 
3. m_runThread gets state changes without verifying corresponding operations. For example, it is set to true even though you don't really test to see if AfxBeginThread was able to start the thread or not.
 
4. You culd declare some of the functions as const that only return data without modifying the class member data.

GeneralRe: Comments and Suggestions PinmemberPEK9:56 2 Aug '05  
GeneralRe: Comments and Suggestions PinmemberBlake Miller10:17 2 Aug '05  
GeneralRe: Comments and Suggestions PinmemberPEK9:33 4 Aug '05  
GeneralRe: Comments and Suggestions PinmemberBlake Miller11:00 4 Aug '05  
GeneralRe: Comments and Suggestions PinmemberPEK10:40 5 Aug '05  
GeneralRe: Comments and Suggestions PinmemberBlake Miller10:51 5 Aug '05  
GeneralRe: Comments and Suggestions PinmemberPEK1:10 6 Aug '05  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120529.1 | Last Updated 23 Aug 2005
Article Copyright 2005 by PEK
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid