Easy, safe Threads
Site Map Feedback

Download:

Up Controls Files Moving Data
First make sure you have a MultiThreaded Application set up: [Project][Settings][C/C++][Code Generation][Use Run-time Library] should have a Multithreaded option selected.
I've wrapped everything you need in a class called CThread.
CThread is an abstract class that allows a derived class to run a Main() function in a separate Thread.
This is the shortest and safest code to use and extend for the control of Threads.
I use ::CreateThread because you don't need to use DuplicateHandle to get the Thread's Handle and you don't need a Window to create the Thread.
I create my own implementation of Sleep(Time) which uses MsgWaitForMultipleObjects to avoid hanging and deadlocking.
When the class gets destroyed the destructor offers any running Thread the chance to exit gracefully.
If a Thread doesn't Stop within 3 seconds of being told to, it is considered hung and gets Terminated.

To use it, put the code that is to run in a separate Thread in a class derived from CThread and impement a void CMain():
Here's an example for a CDialog:
class CFManClientDlg : public CDialog, public CThread {
public:
  CFManClientDlg(CWnd* pParent = NULL) {Start();} // <--This starts the new Thread running the Main() function;
  void Main() {
    ...
  }
  ...
};
This example makes a Window with a counting TitleBar:
class CMyThread : public CThread {
  CWnd* Owner;
public:
  CMyThread(CWnd* pWnd) : Owner(pWnd) {}
  void Main() {
    CString S, Old;
    Owner->GetWindowText(Old);
    int i=0;
    while(!Abort) { // Exit quickly and safely when Abort is true.
      S.Format("%i", ++i);
      Owner->SetWindowText(S);
      Sleep(200);
    }
//  for(;;); // hang the thread to test TerminateThread. If you uncomment this and click [Start] or [Stop] you'll get Memory leaks (being the CStrings [S] and [Old]) because the Thread was Terminated.
    if(::IsWindow(Owner->m_hWnd)) Owner->SetWindowText(Old);
  }
};
To use CMythread, create a Dialog Application (called ThreadTester in this example) with a couple of buttons [Start] and [Stop].
In the dialog header put the above CMyThread class definition and an #include to Thread.h, and:
  virtual ~CThreadTesterDlg() {delete Thread;}
  CMyThread* Thread;
In the .cpp file add these lines to OnInitDialog():
  Thread=new CMyThread(this);
  Thread->Start();
Then use ClassWizard to add button Handlers for the Start and Stop Buttons and make them look like this:
  void CThreadTesterDlg::OnStart() {if(!Thread->Start()) Thread->Main();} // If you can't do it in a separate Thread, do it in this one.
  void CThreadTesterDlg::OnStop () {if(!Thread->Stop ()) SetWindowText(Thread->IsRunning() ? "Runaway Thread!" : "Thread had hung!");}
When you click [Start] the Dialog's Title Bar will start counting.
When you click [Stop] the Dialog's Title Bar will be restored to the Application's Title.
Clicking [Start] is the same as clicking [Stop][Start].

I have also made an example Project called Bouncer which demonstrates the usage of CThread in various ways:

Multithreading Mutual Exclusion (Mutex) Lock class

Thread.h also contains a Multithreading Lock class CLock (nothing to do with clocks)!
Here's an example of its usage:
#include <vector>

template <class T>
class CLockVector : public std::vector<T>, public CLock {
public:
  CLockVector() : vector<T>() {if(!Lock.Lockable() Panic();}
  virtual ~CLockVector() {}
  void Insert(T& obj) {
    CLockedSection LockedSection(Lock);
    vector<T>::push_back(obj);
  }
};

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.