+ ExitCode rc = 0;
+
+ // Delete() is always safe to call, so consider all possible states
+ if ( IsPaused() )
+ Resume();
+
+ if ( IsRunning() )
+ {
+ if ( IsMain() )
+ {
+ // set flag for wxIsWaitingForThread()
+ s_waitingForThread = TRUE;
+
+ wxBeginBusyCursor();
+ }
+
+ HANDLE hThread;
+ {
+ wxCriticalSectionLocker lock(m_critsect);
+
+ p_internal->Cancel();
+ hThread = p_internal->GetHandle();
+ }
+
+ // 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;
+ do
+ {
+ result = ::MsgWaitForMultipleObjects
+ (
+ 1, // number of objects to wait for
+ &hThread, // the objects
+ FALSE, // don't wait for all objects
+ INFINITE, // no timeout
+ QS_ALLEVENTS // return as soon as there are any events
+ );
+
+ switch ( result )
+ {
+ case 0xFFFFFFFF:
+ // error
+ wxLogSysError(_("Can not wait for thread termination"));
+ Kill();
+ return (ExitCode)-1;
+
+ case WAIT_OBJECT_0:
+ // thread we're waiting for terminated
+ break;
+
+ case WAIT_OBJECT_0 + 1:
+ // new message arrived, process it
+ if ( !wxTheApp->DoMessage() )
+ {
+ // WM_QUIT received: kill the thread
+ Kill();
+
+ return (ExitCode)-1;
+ }
+
+ if ( IsMain() )
+ {
+ // give the thread we're waiting for chance to exit
+ // from the GUI call it might have been in
+ if ( (s_nWaitingForGui > 0) && wxGuiOwnedByMainThread() )
+ {
+ wxMutexGuiLeave();
+ }
+ }
+
+ break;
+
+ default:
+ wxFAIL_MSG(_T("unexpected result of MsgWaitForMultipleObject"));
+ }
+ } while ( result != WAIT_OBJECT_0 );
+
+ if ( IsMain() )
+ {
+ s_waitingForThread = FALSE;
+
+ wxEndBusyCursor();
+ }
+
+ if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) )
+ {
+ wxLogLastError("GetExitCodeThread");
+
+ rc = (ExitCode)-1;
+ }
+
+ wxASSERT_MSG( (LPVOID)rc != (LPVOID)STILL_ACTIVE,
+ _T("thread must be already terminated.") );
+
+ ::CloseHandle(hThread);
+ }
+
+ return rc;