Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to run modeless dialog in a separate thread??? PLEASE

179 views
Skip to first unread message

Chris Severtson

unread,
Aug 5, 1999, 3:00:00 AM8/5/99
to

As some of you know already, I have a deadlock situation :^(

My knowledge of Windows is limited and made up about 40% of hearsay. To put it simply, I did not even try to program Windows until this project (which started about two months ago). I mostly write code for embedded systems.

But I realized that since my deadlock is occurring when multiple threads are trying to add entries to a CListBox in a child dialog (I use Create() to instantiate it) that is running in the same thread as almost everything else, this dialog should be in its own thread.

I have spent two hours searching MSDN online but I cannot find the answer to something that I think (I hope) should be simple: How do I run/instantiate/execute/do a modeless dialog in a separate thread?

I keep running into references to CWinThread. But, that doesn't seem to help since it doesn't indicate how to create a modeless dialog that executes within it without the thread just ending after creating the dialog.

I could just launch a thread and execute Create() within it, but then it just exits and the dialog is gone.

I could just launch a thread and execute DoModal() within it, but then it blocks the parent dialog.

This really cannot be that hard!

Would someone PLEASE explain to a newbie? Some simple example code (or a pointer to it) would be great!!


Chris (Hoping I can repay the favor if you people ever get into embedded systems)

chris.vcf

Uwe Kotyczka

unread,
Aug 5, 1999, 3:00:00 AM8/5/99
to Chris Severtson
You could have a thread function to start with AfxBeginThread(<yourFunc>, ...);
The <yourFunc> can create that modeless dialog. Next you can do some WaitForSingleObject function.
I.e. you thread waits for some events (such as main thread exit or some other.).

Have a look at some sample code:
in MyDoc.cpp:
CMyDoc::CMyDoc()
{
...
m_hEventStartCalculate = CreateEvent(NULL, FALSE, FALSE, NULL); // auto reset, initially reset
m_hEventCalculateDone = CreateEvent(NULL, TRUE, TRUE, NULL); // manual reset, initially set
m_hEventKillCalculateThread = CreateEvent(NULL, FALSE, FALSE, NULL); // auto reset, initially reset
m_hEventCalculateThreadKilled = CreateEvent(NULL, FALSE, FALSE, NULL); // auto reset, initially reset

m_pCalculateWorkerThread = NULL;
}

CMyDoc::~CMyDoc()
{
// In this application, the document owns the worker thread.
// The document's destructor is responsible for killing the active worker
// thread.

// It's a good idea to wait for the worker thread to notify via a
// "thread killed" event that it has killed itself. Otherwise, in the case
// where the app is terminating, is possible (even if unlikely) that it
// will detect a memory leak of the CWinThread object before the
// CWinThread object has had a chance to auto-delete itself.

DWORD dwExitCode;
if (m_pCalculateWorkerThread != NULL &&
GetExitCodeThread(m_pCalculateWorkerThread->m_hThread, &dwExitCode) &&
dwExitCode == STILL_ACTIVE)
{
// Kill the worker thread by setting the "calculate done" and "kill thread" events.
SetEvent(m_hEventKillCalculateThread);
SetEvent(m_hEventCalculateDone);
SetEvent(m_hEventStartCalculate);
WaitForSingleObject(m_hEventCalculateThreadKilled, INFINITE);
}
}

void CMyDoc::CalculateInThread(int kindOfThreadProcedure)
{
CMainFrame *pMainFrame = (CMainFrame *)AfxGetMainWnd();
CView* pView;

if (m_pCalculateWorkerThread == NULL)
{
// Begin the worker thread. It is ok to fill in the CThreadInfo
// structure after the thread has started, because the thread
// waits for the "start calculate" event before referring to the structure.
m_pCalculateWorkerThread =
AfxBeginThread(CalculateThreadProc, this);
}

// abort if calculation is in progress
if (WaitForSingleObject(m_hEventCalculateDone, 0) != WAIT_OBJECT_0)
return;

m_nKindOfThreadProcedure = kindOfThreadProcedure;

POSITION pos = GetFirstViewPosition();
ASSERT(pos != NULL);
while (pos != NULL)
{
pView = GetNextView(pos);
if (pView->IsKindOf(RUNTIME_CLASS(CMyView)))
{
break;
}
}
ASSERT(pView != NULL && pView->IsKindOf(RUNTIME_CLASS(CMyView)));
m_hwndNotifyCalculateDone = pView->m_hWnd;
m_hwndNotifyProgress = pMainFrame->m_hWnd;

// The events are initially set or reset in the CreateEvent call;
// but they may be left in an improperly initialized state if
// a worker thread has been previously started and then prematurely
// killed. Set/reset the events to the proper initial state.
// Set the "start calculate" event last, since it is the event the
// triggers the starting of the worker thread calculation.
ResetEvent(m_hEventKillCalculateThread);
ResetEvent(m_hEventCalculateThreadKilled);
SetEvent(m_hEventCalculateDone);
SetEvent(m_hEventStartCalculate);
}

in WorkerThread.cpp:
UINT CalculateThreadProc(LPVOID pParam /* CMyDoc ptr */)
{
CMyDoc* pDoc = (CMyDoc*)pParam;

// This calculate thread runs in an infinite loop, waiting to calculate the
// result whenever the main application thread sets the "start calculate" event.
// The calculate thread exits the loop only when the main application sets the
// "kill calculate" event.

BOOL bAbort, bSuccess;
while (TRUE)
{
bAbort = TRUE;

// Wait until the main application thread asks this thread to do
// another calculation.
if (WaitForSingleObject(pDoc->m_hEventStartCalculate, INFINITE)
!= WAIT_OBJECT_0)
break;

// Exit the thread if the main application sets the "kill calculate"
// event. The main application will set the "start calculate" event
// before setting the "kill calculate" event.
if (WaitForSingleObject(pDoc->m_hEventKillCalculateThread, 0)
== WAIT_OBJECT_0)
break; // Terminate this thread by existing the proc.

// Reset event to indicate "not done", that is, calculation is in progress.
ResetEvent(pDoc->m_hEventCalculateDone);

switch(pDoc->m_nKindOfThreadProcedure)
{
case 0:
DoSomeCalc0(pDoc, bAbort);
break;
case 1:
bSuccess = DoSomeCalc1(pDoc, bAbort);
break;
case 2:
DoSomeCalc2(pDoc, bAbort);
break;
default:
{}
}

// Set event to indicate that calculation is done (i.e., no longer in progres),
// even if perhaps interrupted by "kill calc" event detected in some calc function.
SetEvent(pDoc->m_hEventCalculateDone);

if (WaitForSingleObject(pDoc->m_hEventKillCalculateThread, 0)
== WAIT_OBJECT_0)
break; // terminate this thread by exiting the proc.

if (!bAbort)
::PostMessage(pDoc->m_hwndNotifyCalculateDone,
WM_CALCULATE_IN_THREAD_DONE, pDoc->m_nKindOfThreadProcedure, bSuccess);
}
SetEvent(pDoc->m_hEventCalculateThreadKilled);

return 0;
}

Hope this helps.

Chris Severtson schrieb:

Chris Severtson

unread,
Aug 5, 1999, 3:00:00 AM8/5/99
to Uwe Kotyczka

Uwe,

Thank you for the example code, but I need to execute this child dialog in a user-interface thread so that it has a message pump.


Chris

chris.vcf
0 new messages