AfxGetMainWnd in worker threads

Recently I faced an issue in one of my project code bases. There is a worker thread (created using CreateThread native API) which calls AfxGetMainWnd() MFC function and since worker threads doesn’t have a main window associated with it, CWnd::Create( …WS_CHILD… ) call fails. A window created with WS_CHILD needs a parent window but AfxGetMainWnd() returned NULL hence the crash.

So I searched using Google and found suggestions ranging from sending window handle as the custom parameter to the thread and then passing this on to the function were the Create function call is made! But that call is about 20 functions deep :roll:. The calls go from one class to another, this means I’ve got to carry this darn handle that far, naah I decided, I’m not going to do that. So I set about exploring other possibilities.

Then a pretty cool thought 💡 struck me, AfxGetMainWnd() calls AfxGetThread(), which returns NULL which in turn results in a NULL window handle. So I thought a possible solution will be to create a CWinThread object using AfxBeginThread(WorkerThread). Then another novel thought came that I can set the main window’s handle to m_pMainWnd member variable of this CWinThread object…

[sourcecode language=”cpp”]CWinThread* pThread = AfxBeginThread( (AFX_THREADPROC)ThreadProc,
(LPVOID)this,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED,
NULL );
pThread->m_pMainWnd = AfxGetMainWnd(); // Possibly already set by above call
pThread->ResumeThread();[/sourcecode]

So this does the trick for me and my project. Now calls to AfxGetMainWnd in this worker thread succeeds, haven’t seen any issue with this so far. If you find any, please post as a comment.

3 thoughts on “AfxGetMainWnd in worker threads

  1. You cannot guarantee that pThread->m_pMainWnd = AfxGetMainWnd(); in main thread is executed before the instructions in you worker thread that use the m_pMainWnd. Believe me, it will break someday.

    quote from http://www.codeproject.com/KB/threads/usingworkerthreads.aspx

    The workaround is to obtain a pointer to the application’s main window by calling AfxGetMainWnd in the primary thread, and store it in a place (such as a member variable of the class) where the worker thread can find it.

    • This thread is created in suspended mode. And it’s resumed after

      pThread->m_pMainWnd = AfxGetMainWnd();

      statement. Note the CREATE_SUSPENDED flag in AfxBeginThread call. So this should be safe.

  2. You get this when you try to call AfxGetMainWnd () from an other thread (has to do with thread local storage)

    Try AfxGetApp ()->GetMainWnd () instead.

Appreciate your comments...