Home > MFC > AfxGetMainWnd in worker threads

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…

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();

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.

Advertisements
  1. Michael
    December 22, 2009 at 7:13 pm

    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.

    • December 23, 2009 at 9:13 am

      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.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: