+ ExitCode rc = 0;
+
+ // Delete() is always safe to call, so consider all possible states
+
+ // we might need to resume the thread, but we might also not need to cancel
+ // it if it doesn't run yet
+ bool shouldResume = FALSE,
+ shouldCancel = TRUE,
+ isRunning = FALSE;
+
+ // check if the thread already started to run
+ {
+ wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
+
+ if ( m_internal->GetState() == STATE_NEW )
+ {
+ // WinThreadStart() will see it and terminate immediately, no need
+ // to cancel the thread - but we still need to resume it to let it
+ // run
+ m_internal->SetState(STATE_EXITED);
+
+ Resume(); // it knows about STATE_EXITED special case
+
+ shouldCancel = FALSE;
+ isRunning = TRUE;
+
+ // shouldResume is correctly set to FALSE here
+ }
+ else
+ {
+ shouldResume = IsPaused();
+ }
+ }
+
+ // resume the thread if it is paused
+ if ( shouldResume )
+ Resume();
+
+ TID hThread = m_internal->GetHandle();
+
+ if ( isRunning || IsRunning())
+ {
+ if (IsMain())
+ {
+ // set flag for wxIsWaitingForThread()
+ gs_bWaitingForThread = TRUE;
+ }
+
+ // ask the thread to terminate
+ if ( shouldCancel )
+ {
+ wxCriticalSectionLocker lock(m_critsect);
+
+ m_internal->Cancel();
+ }
+
+#if 0
+ // we can't just wait for the thread to terminate because it might be
+ // calling some GUI functions and so it will never terminate before we
+ // process the Windows messages that result from these functions
+ DWORD result = 0; // suppress warnings from broken compilers
+ do
+ {
+ if ( IsMain() )
+ {
+ // give the thread we're waiting for chance to do the GUI call
+ // it might be in
+ if ( (gs_nWaitingForGui > 0) && wxGuiOwnedByMainThread() )
+ {
+ wxMutexGuiLeave();
+ }
+ }
+
+ result = ::DosWaitThread(&hThread, DCWW_NOWAIT);
+ // FIXME: We ought to have a message processing loop here!!
+
+ switch ( result )
+ {
+ case ERROR_INTERRUPT:
+ case ERROR_THREAD_NOT_TERMINATED:
+ break;
+ case ERROR_INVALID_THREADID:
+ case NO_ERROR:
+ // thread we're waiting for just terminated
+ // or even does not exist any more.
+ result = NO_ERROR;
+ break;
+ default:
+ wxFAIL_MSG(wxT("unexpected result of DosWaitThread"));
+ }
+ if ( IsMain() )
+ {
+ // event processing - needed if we are the main thread
+ // to give other threads a chance to do remaining GUI
+ // processing and terminate cleanly.
+ wxTheApp->HandleSockets();
+ if (wxTheApp->Pending())
+ if ( !wxTheApp->DoMessage() )
+ {
+ // WM_QUIT received: kill the thread
+ Kill();
+
+ return wxTHREAD_KILLED;
+ }
+ else
+ wxUsleep(10);
+ }
+ else
+ wxUsleep(10);
+ } while ( result != NO_ERROR );
+#else // !wxUSE_GUI
+ // simply wait for the thread to terminate
+ //
+ // OTOH, even console apps create windows (in wxExecute, for WinSock
+ // &c), so may be use MsgWaitForMultipleObject() too here?
+ if ( ::DosWaitThread(&hThread, DCWW_WAIT) != NO_ERROR )
+ {
+ wxFAIL_MSG(wxT("unexpected result of DosWaitThread"));
+ }
+#endif // wxUSE_GUI/!wxUSE_GUI
+
+ if ( IsMain() )
+ {
+ gs_bWaitingForThread = FALSE;
+ }
+ }
+
+#if 0
+ // although the thread might be already in the EXITED state it might not
+ // have terminated yet and so we are not sure that it has actually
+ // terminated if the "if" above hadn't been taken
+ do
+ {
+ if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) )
+ {
+ wxLogLastError(wxT("GetExitCodeThread"));
+
+ rc = (ExitCode)-1;
+ }
+ } while ( (DWORD)rc == STILL_ACTIVE );
+#endif
+
+ if ( IsDetached() )
+ {
+ // if the thread exits normally, this is done in WinThreadStart, but in
+ // this case it would have been too early because
+ // MsgWaitForMultipleObject() would fail if the thread handle was
+ // closed while we were waiting on it, so we must do it here
+ delete this;
+ }
+
+ if ( pRc )
+ *pRc = rc;
+
+ return rc == (ExitCode)-1 ? wxTHREAD_MISC_ERROR : wxTHREAD_NO_ERROR;