Re: returning from worker thread
SuspendThread is gone; I'm using WSFO. I got the message loud and clear;
and now I realize that you guys also weaned me off of my timers, so that I'm
having two threads talk to each other. I'm getting there.
2 questions, related variously to comments buried below:
1) I will be moving my audio thread pointer to become a member of my view.
But even then, I was thinking that it was better not to call the audio
class' CleanUp function and the view's AudioSignal function from within the
thread, but rather to leave the worker thread as soon as possible and do the
other tasks in the main thread. My thinking has been that it is better to
let the audio thread function basically act as a switch and not much more;
and also that it was somehow safer to let the other classes do their work in
the main thread. I believe there is both truth and fiction in this mindset.
Can you comment?
2) What's wrong, at shutdown, with signaling the audio thread's WFSO (which
waits for the audio event handle) with SetEvent? With the help of just one
more flag variable, the switch statement could then determine whether audio
has been interrupted or not and then take the appropriate action before
returning zero? Although I have my code torn apart right now, I have been
using something like this inside the audio class, which currently owns the
thread pointer:
DWORD threadstatus;
if(m_pAudioThread)
{
::GetExitCodeThread(m_pAudioThread->m_hThread, &threadstatus);
if(threadstatus == STILL_ACTIVE)
{
Interrupt(2); // signal audio thread
::WaitForSingleObject(m_pAudioThread->m_hThread,50);
}
}
---------------
"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message
news:r5q1e25q1sb68fpsdhtv1m9b0uep8csr6n@4ax.com...
As already pointed out, ResumeThread/SuspendThread is a truly lousy way of
doing business.
It might work on good days, bbut on bad days it will fail horribly. Just
lose it
completely. The only thing you can use ResumeThread for is startingthe
thread off if you
created it suspended. The rest of the time, it doesn't exist.
SuspendThread never exists
for practical programming problems.
How *did* you provide for shutdown, since there's nothing in your code to
handle it (don't
say "TerminateThread", either, as that is a Really, Really, Really Bad
Idea.)
NEVER assume that if you get a return value from WFSO that is not
WAIT_OBJECT_0 that you
"know" what it means. There is no valid reason to assume that you have
any idea what has
just happened if it fails, and different falures may have different
requirements (such as
what you have to fix in your program). A switch statement is best
practice.
switch(WaitForSingleObject(...))
{ /* WFSO */
case WAIT_OBJECT_0:
break;
case WAIT_FAILED:
ASSERT(FALSE);
...cleanup
return;
default:
ASSERT(FALSE);
....cleanup
return;
} /* WFSO */
See below...
*****
On Sat, 12 Aug 2006 14:49:40 -0400, "Steve Russell"
<srussell@removethisinnernet.net>
wrote:
I realize my posts in this thread are possibly becoming an annoyance as I
juggle and struggle among varying issues and code attempts. But this
particular question is not related to shutdown, which actually was
provided
for before experimenting with the advice I have received. May I ask
this --
Assuming that my audio class waveOut calls m_pAudioThread->ResumeThread(),
is there anything in my worker thread function below that would appear
problematic specifically in relation to being able to post a message to my
view and retain valid pointers?
UINT AudioThreadFunc(LPVOID pParam)
{
while(TRUE)
{
CAudioFile* audiofile = (CAudioFile*)pParam;
if(WaitForSingleObject(audiofile->m_hndDone,INFINITE) != WAIT_OBJECT_0)
// error handling goes here
return 0;
}
CloseHandle(audiofile->m_hndDone);
if(audiofile->m_pView->m_hWnd)
*****
Since you have no guarantee that audiofile->m_pView is valid, this code is
inherently
flawed. Note that GetSafeHwnd() would not be valid either, because the
pointer might now
point to free space in the heap but the value in it is not 0, so this
entire test is
nonsensical. Do not use it. You must make sure this thread has
completely terminated
before you can allow the view to be destroyed. Therefore, there is no
reason to look at
the m_hWnd of the pView pointer because it WILL be valid because you have
MADE SURE IT IS!
*****
audiofile->m_pView->PostMessage(WM_AUDIO_CLEANUP, 1); // handler
calls m_pAudioFile->AudioCleanUp()
else
audiofile->AudioCleanUp(false);
*****
Why are you assuming that the m_pAudioFile in the view is still valid? In
fact, you
passed it in as parameter, so there is no reason to call it via the view.
Either you call
it here always, because you have the file here, or you go through the
view, but this
conditional logic is wrong. The fact that it has to exist suggests you
have deeper
problems in your threading.
*****
::SuspendThread(audiofile->m_pAudioThread->m_hThread);
*****
Lose it. Just lose it. This is just completely wrong. For all the
reasons already
pointed out, it can't work, so all it does is introduce the probability of
serious
failure.
*****
}
return 0;
}
---------------
"Scott McPhillips [MVP]" <org-dot-mvps-at-scottmcp> wrote in message
news:eByn7ljvGHA.4688@TK2MSFTNGP06.phx.gbl...
Steve Russell wrote:
Even with keeping the thread alive, I find, in Release, that using
audiofile->m_pView->PostMessage(WM_AUDIO_CLEANUP)
instead of calling audiofile->CleanUp() directly in the thread
leads to trouble with the view pointer eventually. Aside from needing
to
change my threading design, I would sure appreciate an explanation as
to
how this could be happening. If I the thread isn't being destroyed,
how
is it that the audio class pointer passed to my thread function would
fail?
Your code outline has not shown any provision for thread shutdown at
program close. The likely problem with the view pointer is that the
view
object gets destroyed before the thread has exited. This opens the door
for the thread to use an invalid pointer.
You must control the program shutdown sequence so the thread is gone
before any shared data, such as a view pointer, becomes invalid. Several
posts in this thread, as well as the Newcomer tutorials, point this out
and mention ways to do it. Data known to the thread must remain valid
until after the thread has exited!
--
Scott McPhillips [VC++ MVP]
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm