Re: Multithreaded long process update window
  Home FAQ Contact Sign in
microsoft.public.vc.mfc only
 
Advanced search
POPULAR GROUPS

more...

 Up
Re: Multithreaded long process update window         

Group: microsoft.public.vc.mfc · Group Profile
Author: AliR (VC++ MVP)
Date: Feb 21, 2008 13:13

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
>
no comments
diggit! del.icio.us! reddit!

RELATED THREADS
SubjectArticles qty Group
Windows XP and Windows Vista ExpertZone chat tomorrow, June 5th 10am PSTmicrosoft.public.windows.vista.mail ·