Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

VC++: CWinThread for simple threads

Posted on 1998-07-16
8
Medium Priority
?
2,877 Views
Last Modified: 2008-02-01
Hi,

I'd like to use CWinThread to create a simple, worker thread. I've used AfxBeginThread in the past, but CWinThread seems more encapsulated. This is probably really easy, but as usual the documentation in Visual C is horrible and I can't make heads or tails out of it.

What I'm doing is creating a derivation of CWinThread called CThinker with an overridden Run(). Whenever I want a thread I create a new CThinker object and call CreateThread, which returns TRUE, but somehow my Run() function never gets called.

What am I doing wrong? If this turns out to be more complicated then I think, I will add points.
0
Comment
Question by:Slarti
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
8 Comments
 
LVL 7

Expert Comment

by:galkin
ID: 1167965
If you want to crate a worker thread user other version of overloaded function AfxBeginThread that is passed pointer to thread entry point function. As this function returns worker thread exits. If you create UI thread derive class from CWinThread. run virtual function contains message pump for all windows created from current thread. This message pump exits when thread is sent WM_QUIT message generally when main window is closed. When message pump exits, Run returns then ExitInstance is called and thread is terminated.  
0
 
LVL 2

Author Comment

by:Slarti
ID: 1167966
galkin,
You didn't really answer my question. As I said, I already know how to use AfxCreateThread to create worker threads. I want to avoid this. What I want is to create a worker thread which is derived from CWinThread. According to the documentation, this should be possible, but there are not examples that I could find on how to do this.
By the way, it is incorrect that "As this function [AfxCreateThread] returns worker thread exits". AfxCreateThread returns immediately after the worker thread begins working. The thread then terminates without notifying its creator.
0
 
LVL 2

Author Comment

by:Slarti
ID: 1167967
galkin,
You didn't really answer my question. As I said, I already know how to use AfxCreateThread to create worker threads. I want to avoid this. What I want is to create a worker thread which is derived from CWinThread. According to the documentation, this should be possible, but there are not examples that I could find on how to do this.
By the way, it is incorrect that "As this function [AfxCreateThread] returns worker thread exits". AfxCreateThread returns immediately after the worker thread begins working. The thread then terminates without notifying its creator.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 7

Expert Comment

by:galkin
ID: 1167968
It terminates because your worker thread doesn't contain any windows so message pump implemented in Run function exits immediately so thread is terminated.
0
 
LVL 2

Author Comment

by:Slarti
ID: 1167969
But I've overridden the Run function entirely, and it never even gets called.
Can you give me a simple, step-by-step list of instructions on what to do to get a worker thread to run when it is derived from CWinThread?

0
 
LVL 7

Accepted Solution

by:
galkin earned 90 total points
ID: 1167970
It is not called because you didn't override InitInstance function that by default returns FALSE and Run is never called. I rsuggest you stepping into AfxBeginThread and looking at how it works.
0
 
LVL 2

Author Comment

by:Slarti
ID: 1167971
I will do that and get back to you.
0
 
LVL 2

Author Comment

by:Slarti
ID: 1167972
Well, that's not much of an answer, but it did lead me to the correct answer eventually. Since I am in the habit of documenting such problems for my own later use, I am attaching a description of the problem and solution for people who use this as a PAQ.

Incomplete Entries in the Online Help
 ·  Undocumented CWinThread constructor. CWinThread has two constructors. The first, CWinThread::CWinThread(), receives no parameters and does not initialize the function pointer within it. This constructor is documented briefly. The second constructor is undocumented and is the more commonly used constructor (it is used by AfxBeginThread). Here is a description.
  CWinThread::CWinThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam)
  Constructs a CWinThread object, and sets the thread procedure to pfnThreadProc and the parameter which is passed to this thread procedure to pParam. This constructor, together with the CWinThread::CreateThread() function, is identical to using the worker thread version of AfxCreateThread, except that AfxCreateThread performs some error checking and also has a version for non-multitasking compilations. For an example of the use of this constructor to create and execute a thread, see the source for AfxCreateThread, in mfc\src\thrdcore.cpp, line 151.
 ·  Incomplete documentation for CWinThread::m_bAutoDelete. In the help entry for CWinThread::m_bAutoDelete (search for m_bAutoDelete in the help index), the default value is not mentioned. The default value is TRUE. The use of m_bAutoDelete is described in more detail in the article Multithreading: Terminating Threads in the online help.
 ·  Detailed instructions for creating worker threads derived from CWinThread. The online help recommends using AfxBeginThread to create worker threads, but this requires the creation of a global function for the thread procedure, which violates information hiding and encapsulation. One can also create worker threads by deriving a class from CWinThread. Follow the following instructions:
  1 . Derive a class from CWinThread. There is no need to call the CWinThread constructor from the derived constructor. Override the function CWinThread::Run() to contain whatever you want the thread to do. If your class contains any data members, declare a virtual destructor, even if you leave it empty (see step 5).
  2 . Override the function CWinThread::InitThread() so that it always returns TRUE. This tells the CWinThread initialization routines to call Run(). If InitThread() returns FALSE for some reason, the thread will terminate immediately, before calling Run(). No error message will be displayed. (This is what happened to me.)
  3 . Before beginning the thread, dynamically construct an object of the derived type using operator new. Dynamic allocation is very important, because the object will be deleted by the thread itself and local objects cannot be deleted by other threads.
  4 . To begin a thread, call the object’s member function CreateThread(). The object can be constructed at any point; the thread begins executing only when CreateThread() is called. Different objects can be used to create simultaneous threads using the same Run() function.
  5 . The thread terminates when Run() returns. The object is then deleted automatically by the encapsulating CWinThread functions, which is why you should declare a virtual destructor, even if it does nothing.

0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

661 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question