I couldn't recreate this problem.
What I did was create a CWinThread class, in it's InitInstance, I called
Sleep(5000); and then AfxMessageBox("Box1");
Then from the CWinApp::InitInstance, I created the thread, called
Sleep(20000);, and then AfxMessgaeBox("Box2);
Box1 showed up after ~ 5 seconds, and Box2 after 20
I personally would have used waitable timers in the thread instead of sleep.
#pragma once
#include
typedef CMap TimerMap;
// CDialogThread
class CDialogThread : public CWinThread
{
DECLARE_DYNCREATE(CDialogThread)
protected:
CDialogThread(); // protected constructor used by dynamic
creation
virtual ~CDialogThread();
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
protected:
virtual BOOL OnIdle(LONG lCount);
DECLARE_MESSAGE_MAP()
private:
HANDLE SetTimer(LONGLONG Milliseconds);
void KillTimer(HANDLE &Handle);
void OnTimer(HANDLE Handle);
HANDLE m_TimerHandle;
TimerMap m_Timers;
};
// DialogThread.cpp : implementation file
//
#include "stdafx.h"
#include "DelayedStartTest.h"
#include "DialogThread.h"
// CDialogThread
IMPLEMENT_DYNCREATE(CDialogThread, CWinThread)
CDialogThread::CDialogThread()
{
}
CDialogThread::~CDialogThread()
{
}
BOOL CDialogThread::InitInstance()
{
m_TimerHandle = SetTimer(5000);
return TRUE;
}
int CDialogThread::ExitInstance()
{
// TODO: perform any per-thread cleanup here
return CWinThread::ExitInstance();
}
BEGIN_MESSAGE_MAP(CDialogThread, CWinThread)
END_MESSAGE_MAP()
// CDialogThread message handlers
HANDLE CDialogThread::SetTimer(LONGLONG Milliseconds)
{
HANDLE Handle = CreateWaitableTimer(NULL,TRUE,NULL);
LARGE_INTEGER liDueTime;
liDueTime.QuadPart= Milliseconds * -10000;
if (!SetWaitableTimer(Handle,&liDueTime,0,NULL,NULL,TRUE))
{
CloseHandle(Handle);
ASSERT(FALSE);
return NULL;
}
m_Timers.SetAt(Handle,Handle);
return Handle;
}
void CDialogThread::KillTimer(HANDLE &Handle)
{
if (Handle != NULL)
{
CancelWaitableTimer(Handle);
CloseHandle(Handle);
m_Timers.RemoveKey(Handle);
Handle = NULL;
}
}
BOOL CDialogThread::OnIdle(LONG lCount)
{
HANDLE *pTimers = new HANDLE[m_Timers.GetCount()];
HANDLE Handle;
POSITION Pos = m_Timers.GetStartPosition();
int i = 0;
while (Pos)
{
m_Timers.GetNextAssoc(Pos,Handle,Handle);
pTimers[i++] = Handle;
}
DWORD Ret =
WaitForMultipleObjects((DWORD)m_Timers.GetCount(),pTimers,FALSE,0);
DWORD Err = GetLastError();
if (Ret != WAIT_TIMEOUT &&
m_Timers.Lookup(pTimers[Ret-WAIT_OBJECT_0],Handle))
{
OnTimer(Handle);
}
delete [] pTimers;
CWinThread::OnIdle(lCount);
return TRUE;
}
void CDialogThread::OnTimer(HANDLE Handle)
{
if (m_TimerHandle == Handle)
{
KillTimer(m_TimerHandle);
AfxMessageBox("The wait dialog in the thread");
}
}
AliR.
"Peter Boulton" perceptions.co.uk> wrote in message
news:fpkndt$6tg$2$830fa17d@news.demon.co.uk...
>I am trying to develop a small window which can appear after a few seconds
>delay if my app needs to wait to open a sql server recordset because some
>of the records it needs are exclusively locked by another user.
>
> In this situation the ado code blocks till the appointed connection
> timeout period and then throws an exception. Rather than having my users
> stare at an hourglass till this happens, I want a message window to appear
> telling them it's waiting to access the data. On the other hand, if I
> make it appear every time and the response from the database is instant
> then I don't want to show it - it will just flash momentarily and
> disappear, which is ugly.
>
> So my idea is this:
>
> - Launch a user interface thread. The thread goes to sleep for, say, 5
> seconds.
> - Open the recordset
> - When the recordset 'opens' we then kill the user interface thread.
> (Therefore if the open takes more than 5 secs the user sees the message
> window, otherwise the thread which creates it gets killed before its
> window is displayed.)
>
> The problem I'm seeing is that where the main thread blocks waiting for
> the recordset to open the user interface thread seems to also block, so
> the window never appears.
>
> I'm starting the new thread with:
>
> m_pMyLongProcess =
> (CLongProcessThread*)AfxBeginThread(RUNTIME_CLASS(CLongProcessThread),
> THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
>
> Then I'm initialising some member variables of m_pMyLongProcess and
> calling m_pMyLongProcess->ResumeThread(); to get the thread running.
>
> In my test code I simulate blocking with:
>
> StartNewThread(); // This fn contains AfxBeginThread, the member
> initialisations for the thread class, and ResumeThread()
> Sleep(10000);
> AfxMessageBox("Awake!");
>
> (The AfxMessageBox serves no function other than to alert me that the main
> thread has finished sleeping. The user interface thread window appears
> simultaneously with the message box.)
>
> On this code, the window launched in the user-interface thread appears
> after the Sleep(10000) period rather than the 5 seconds (or whatever)
> Sleep() in my user-interface thread. Which seems wrong - surely the
> Sleep() should apply to the thread and not the process? (I hope I've
> explained this clearly! I fear I'm missing something fairly fundamental
> as I try to avoid threads as much as possible!) For anyone interested
> enough, you can download my full test project at:
>
>
http://www.dataper.demon.co.uk/misc/LongProcessWndExample.zip
>
> It's a small 135k zip. The thread is launched from the document. The
> code for the user interface thread is in LongProcessThread.cpp/h. There
> is a main menu option to mess around with dynamically changing the text on
> the window.
>
> I'm looking for enlightenment! Thanks.
>
> Pete
>