From: Goran on
Whoops, how wrong was I...

I __presumed__, apparently wrongly, that your thread is a worker
thread without a message loop (but with a thread function).

If you have a message loop, I will be presuming that you did something
like this to create the thread:

pMyThread = AfxBeginThread(..., CREATE_SUSPENDED/*ESSENTIAL*/, ...);
if (NULL = pMyThread) AfxThrowResourceException(); // Or something
else
// Note that AfxBeginThread might throw, too!
pMyThread->m_bAutoDelete = FALSE; // ESSENTIAL
VERIFY(pMyThread->ResumeThread() == 1);

.... and that you are holding onto pMyThread correctly.

If your thread works through a message loop, then forget about a
shared termination flag. Use pMyThread->PostThreadMessage
(WM_SOMETHING). AFAIK, WM_SOMETHING can be WM_QUIT, but note that
WM_QUIT is a bit special (http://blogs.msdn.com/oldnewthing/archive/
2005/11/04/489028.aspx).

In a thread with a message loop, you should _not_ use a shared
"termination" flag. You should NOT use an exception to break out.

Even with a message loop, you should still NOT use AfxTerminateThread.

From the main thread, when you decide to stop pMyThread, you do:

VERIFY(pMyThread->PostThreadMessage(WM_SOMETHING, ...));
VERIFY(WaitForSingleObject(*pMyThread, INFINITE) == WAIT_OBJECT_0);
delete pMyThread; // "Official" MFC way is pMyThread->Delete(). That
is STUPID and I won't do it.

YOU have to make sure, through organization of your code^^^, that the
thread will pick the message up quickly enough so that you don't block
in WFSO for a long time, thereby having e.g. poor user experience
(there's NO magic trick, YOU have to do it).

^^^ "worker" threads with message loops are only good if all they do
are short bursts of activity caused by messages posted to them.

Goran.
From: Joseph M. Newcomer on
See below....
On Fri, 23 Oct 2009 03:16:10 -0700 (PDT), Frank <jerk(a)gmx.de> wrote:

>Dear people,
>
>I create a subthread of my main program by calling
>
>
>AfxBeginThread(RUNTIME_CLASS(CMySubThread));
>
>
>CMySubThread is derived from CWinThread. Eventually,
>I'd like to terminate the thread. So I clean all variables,
>buffer memory and the like, then call AfxEndThread(0)
>from within a member function of CMySubThread.
****
Forget that you ever heard of this function. Do not ever call ExitThread as an API or any
of its thinly-disguised equivalences (such as AfxEndThread). Don't do it. Ever.

To terminate the thread, you return from the top-level thread function. That is the ONLY
correct way to terminate a thread. Any other technique opens you to all kinds of
potentially serious problems.
****
>
>The problem: This call seems to close the whole application,
>it throws an exception in:
>
>(code from AfxEndThread):
>
>AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
>CWinThread* pThread = pState->m_pCurrentWinThread;
>if (pThread != NULL)
> {
> ASSERT_VALID(pThread);
> ASSERT(pThread != AfxGetApp());
>
>
>The last ASSERT causes the problem.
>
>Now there are two questions:
>- Why does the call try to close the whole app
> instead of the thread?
***
Could it be because you are calling AfxEndThread from the main thread? You have give NO
context for where you call it. A classic blunder is

class CMyThread : public CWinThread {
public:
Stop() { AfxEndThread(0); }
};

class CMyView : public CView {
protected:
CMyThread * thread;
Stop() { thread->Stop(); }
};

which of course will stop your app, because while AfxExitThread will exit a thread, *it is
called in the context of your main GUI thread*, and therefore stops your app! This is
because it has meaning ONLY when called from the thread context itself. The above example
does not do that.

But don't ever use AfxExitThread. Exit from your top-level thread function. Since you
have shown no code at all, there is absolutely no way telll what you have done or how to
fix it.
****
>- And how can I safely terminate the thread?
****
If it is a UI thrread, PostQuitMessage(0) from within the thread itself.
joe
****
>
>
>TIA!
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Joseph M. Newcomer on
See below...
On Fri, 23 Oct 2009 07:28:32 -0700 (PDT), Frank <jerk(a)gmx.de> wrote:

>Scott McPhillips wrote:
>
>> The thread must terminate itself. Just because you call from within a
>> member function of the thread class does not mean you are calling from the
>> thread. I.e., calling a function from the main thread means the function
>> executes in the main thread, no matter what class the function is part of.
>>
>> The thread must call PostQuitMessage(0) to exit. Your main thread can
>> request the secondary thread to exit by posting a custom message to it or by
>> signaling an event that the thread monitors.
>
>I tried that: Had the main thread post a message
>to the thread (PostThreadMessage), in the message handler
>
>- call AfxEndThread
****
Forget you ever heard of AfxEndThread. Never, ever, under any imaginable circumstances
should you call it. It does not exist. It is a figment of someone's imagination. Do
not, ever, ever, ever call it yourself.

Note that since you call AfxEndThread, none of the code below will ever be executed! So
it is pointless code.

I'm curious: why does stoppping the thread close the main app. And why would you ever,
EVER want to PostMessage a WM_QUIT to the main GUI thread (answer: because you have no
idea what you are doing!) This function will close the main GUI thread as well. But
worse still, it will stop the message pump even when there are still important messages to
be processed! The WM_CLOSE will close the main thread. STOP RIGHT THERE! DO NOT POST A
WM_QUIT TO THE MAIN MESSAGE LOOP, EVER!
joe

****
>- PostQuitMessage(0)
>- m_pMainWnd->PostMessage(WM_CLOSE, 0, 0)
>- m_pMainWnd->PostMesage(WM_QUIT, 0, 0)
>
>Everything closes the main program.
****
Are you surprised? You asked it to do so.
****
>
>Do I have to do something about the message queue
>of the subthread or something?
****
No. Once you PostQuitMessage to it, you are done.
joe
****
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Frank on
Joseph M. Newcomer wrote:

> On Fri, 23 Oct 2009 07:28:32 -0700 (PDT), Frank <j...(a)gmx.de> wrote:

> >I tried that: Had the main thread post a message
> >to the thread (PostThreadMessage), in the message handler
>
> >- call AfxEndThread
>
> ****
> Forget you ever heard of AfxEndThread.  Never, ever, under any imaginable circumstances
> should you call it.  It does not exist.  It is a figment of someone's imagination.  Do
> not, ever, ever, ever call it yourself.
>
> Note that since you call AfxEndThread, none of the code below will ever be executed!  So
> it is pointless code.

Sorry Joseph, it seems to me that you believe I put all
those statements into the code. My bad. I tried all these
statements but only one at a time.
From: Joseph M. Newcomer on
On Mon, 26 Oct 2009 01:05:04 -0700 (PDT), Frank <jerk(a)gmx.de> wrote:

>Joseph M. Newcomer wrote:
>
>> On Fri, 23 Oct 2009 07:28:32 -0700 (PDT), Frank <j...(a)gmx.de> wrote:
>
>> >I tried that: Had the main thread post a message
>> >to the thread (PostThreadMessage), in the message handler
>>
>> >- call AfxEndThread
>>
>> ****
>> Forget you ever heard of AfxEndThread. �Never, ever, under any imaginable circumstances
>> should you call it. �It does not exist. �It is a figment of someone's imagination. �Do
>> not, ever, ever, ever call it yourself.
>>
>> Note that since you call AfxEndThread, none of the code below will ever be executed! �So
>> it is pointless code.
>
>Sorry Joseph, it seems to me that you believe I put all
>those statements into the code. My bad. I tried all these
>statements but only one at a time.
****
That was not clear. So let's look at them, one at a time:

- call AfxEndThread
Always, without exception, the wrong thing to do
- PostQuitMessage(0)
Yes, this is how you stop your UI thread,
but you must be sure that no other message
can be posted after this one!
- m_pMainWnd->PostMessage(WM_CLOSE, 0, 0)
This tells your app to quit cleanly, except that
is apparently not what you wanted to do
- m_pMainWnd->PostMesage(WM_QUIT, 0, 0)
This kills your app, badly, and is always a mistake
joe
****
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm