I stated that partially incorrectly. My Interrupt() call just before
otherwise I call SetEvent on the event handle. Seems like its working
cleanly, but maybe there's something else I need to know.
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