You should not be calling AfxGetMainWnd in a worker thread

來源:互聯網
上載者:User
Author Problems Initializing in the MainFrame

http://www.codecomments.com/archive372-2006-4-890607.html

Joe

2006-04-14, 7:09 pm

Hi. Iâ€ve seen a very similar message already posed on this topic, but I
didnâ€t see a solution that pertains to my case. I want to add some code to my
MainFrame, and figured that I should do all initialization in the OnCreate().
Is this correct? Anyway, The OnCreate that was generated by the Wizard
(CFormView SDI app) is:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct} {

if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
…

// My test code
CWnd* t = AfxGetMainWnd();

}

If I try to get the frame address with AfxGetMainWnd() as depicted above I
get a NULL.

Is there a better place to put one time initialization code where
AfxGetMainWnd() will actually have the pointer to my MainFrame? I know itâ€s
correct by the time it hits the OnInitialUpdate() in my View – Iâ€m trying to
figure the best place to put the same code in my MainFrame. Obviously, the
“this†pointer is correct inside OnCreate(), but in this part of my
initialization code I need the AfxGetMainWnd() function to return the pointer
to the MainFrame.

Thanks.

Tom Serface

2006-04-14, 7:09 pm

The pointer is assigned when the window is created in InitInstance() (main
code). You could walk through that function and see when the window is
created.

Tom

"Joe" <Joe@discussions.microsoft.com> wrote in message
news:5B834110-CA60-4C52-938F-124302BA497A@microsoft.com...
> Hi. I've seen a very similar message already posed on this topic, but I
> didn't see a solution that pertains to my case. I want to add some code to
> my
> MainFrame, and figured that I should do all initialization in the
> OnCreate().
> Is this correct? Anyway, The OnCreate that was generated by the Wizard
> (CFormView SDI app) is:
>
> int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct} {
>
> if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
> return -1;

Ajay Kalra

2006-04-14, 7:09 pm

"Joe" <Joe@discussions.microsoft.com> wrote in message
news:5B834110-CA60-4C52-938F-124302BA497A@microsoft.com...
> Hi. I've seen a very similar message already posed on this topic, but I
> didn't see a solution that pertains to my case. I want to add some code to
my
> MainFrame, and figured that I should do all initialization in the
OnCreate().
> Is this correct? Anyway, The OnCreate that was generated by the Wizard
> (CFormView SDI app) is:
>
> int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct} {
>
> if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
> return -1;
> .
>
> // My test code
> CWnd* t = AfxGetMainWnd();
>
> }
>
> If I try to get the frame address with AfxGetMainWnd() as depicted above I
> get a NULL.
>

You are using AfxGetMainWnd, which uses a member variable which gets set
later on in CWinApp. In your case, you can use "this" rather than
AfxGetMainWnd.

--
Ajay Kalra [MVP - VC++]
ajaykalra@yahoo.com

David Wilkinson

2006-04-14, 7:09 pm

Joe wrote:

> Hi. Iâ€ve seen a very similar message already posed on this topic, but I
> didnâ€t see a solution that pertains to my case. I want to add some code to my
> MainFrame, and figured that I should do all initialization in the OnCreate().
> Is this correct? Anyway, The OnCreate that was generated by the Wizard
> (CFormView SDI app) is:
>
> int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct} {
>
> if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
> return -1;
> …
>
> // My test code
> CWnd* t = AfxGetMainWnd();
>
> }
>
> If I try to get the frame address with AfxGetMainWnd() as depicted above I
> get a NULL.
>
> Is there a better place to put one time initialization code where
> AfxGetMainWnd() will actually have the pointer to my MainFrame? I know itâ€s
> correct by the time it hits the OnInitialUpdate() in my View – Iâ€m trying to
> figure the best place to put the same code in my MainFrame. Obviously, the
> “this†pointer is correct inside OnCreate(), but in this part of my
> initialization code I need the AfxGetMainWnd() function to return the pointer
> to the MainFrame.
>
> Thanks.

Joe:

AfxGetMainWnd() returns the m_pMainWnd member of your application
object, but in SDI this member is not set until after the main frame,
document and view are created. This can be a problem in the document and
the view. But in the MainFrame itself, you already have the "this"
pointer, so why do you need AfxGetMainWnd()?

Maybe I'm missing something here.

David Wilkinson

Joe

2006-04-14, 7:09 pm

Tom - thanks for the reply. I was hoping to put this code in my MainFrame not
in my App. Do you know of somewhere in my MainFrame I could put it?
Joe

2006-04-14, 7:09 pm

Ajay - thanks for your reply. The problem isnâ€t that I donâ€t know the
MainFrame pointer in my MainFrame (obviously I do), the problem is that Iâ€m
trying to start a thread in my MainFrame. The thread starts OK, but when it
starts it gets the owner window, which when I start the thread in the
MainFrame the owner window is NULL, so when I call AfxGetMainWnd() inside the
thread I always get a NULL pointer (even though the Frame is already created
and the window is visible). I know I can create a function to return a
pointer to the MainFrame, but I didnâ€t have any problem with similar threads
that I started from my View – because the pointer was valid when I created
the thread in MyView::OnInitalUpdate().
Joe

2006-04-14, 7:09 pm

David - thanks for your reply. It looks like you and Ajay were thinking the
same thing at the same time. You can look up at my response to him, but
basically I need AfxGetMainWnd() to work in a thread I'm starting inside the
MainFrame - and it always returns NULL because I'm starting it in the
MainFrame.
Ajay Kalra

2006-04-14, 7:09 pm

You should not be calling AfxGetMainWnd in a worker thread. These
windows pointers are stored in TLS and generally you should not use
them outside the thread these were created. You can pass the window
handle to the thread.

In your case this is what I would do:

In CYouApp::InitInstance, post a custom message to mainframe after it
has been created. In the handler of this message, start your thread. OR

Start your thread in InitInstance after the mainframe is created.

---
Ajay

Joe

2006-04-14, 7:09 pm

Ajay – yeah, I think either way you suggest would work OK, thanks.


> You should not be calling AfxGetMainWnd in a worker thread. These
> windows pointers are stored in TLS and generally you should not use
> them outside the thread these were created.

Iâ€m wondering about your comment. The documentation for AfxGetMainWnd()
says: if the function is called from a secondary thread in the application
(which is what Iâ€m doing), the function returns the main window associated
with the thread that made the call. This is why AfxGetMainWnd() works
properly with I start the thread from CMyView::OnInitalUpdate() and not from
CMainFrame::OnCreate(). Are you thinking that it may not be safe to call it
in any of my Worker threads?

Scott McPhillips [MVP]

2006-04-14, 7:09 pm

Joe wrote:
> Iâ€m wondering about your comment. The documentation for AfxGetMainWnd()
> says: if the function is called from a secondary thread in the application
> (which is what Iâ€m doing), the function returns the main window associated
> with the thread that made the call. This is why AfxGetMainWnd() works
> properly with I start the thread from CMyView::OnInitalUpdate() and not from
> CMainFrame::OnCreate(). Are you thinking that it may not be safe to call it
> in any of my Worker threads?

Worker threads do not have a main window "associated with the thread."
AfxGetMainWnd() should return NULL from such threads.

--
Scott McPhillips [VC++ MVP]

David Wilkinson

2006-04-14, 7:09 pm

Joe wrote:

> David - thanks for your reply. It looks like you and Ajay were thinking the
> same thing at the same time. You can look up at my response to him, but
> basically I need AfxGetMainWnd() to work in a thread I'm starting inside the
> MainFrame - and it always returns NULL because I'm starting it in the
> MainFrame.

Joe:

If this is a worker thread, pass the "this" pointer as LPVOID parameter.

I forget if it is OK to call AfxGetMainWnd() from a thread (Ajay says
not), but if it is, one simple way to get AfxGetMainWnd() to return the
correct value sooner is to do

AfxGetApp()->m_pMainWnd = this;

in your MainFrame constructor. Bad OOP, but effective.

David Wilkinson

Tom Serface

2006-04-14, 7:09 pm

I didn't catch that you were calling this from a worker thread. You need to
be careful about that one since worker threads are not supposed to access
GUI windows. You can send a message to the mainframe to tell it to do
something for you, but you'll have to set the CWnd * pointer by calling a
function in the thread object... I usually use something like:
SetMessageWnd(CWnd *pWnd); Then you can do a pWnd->PostMessage(...) to tell
the GUI thread you want it to do something. However, don't update any of
the windows directly and, I've found, you should use PostMessage rather than
SendMessage.

Tom

"Joe" <Joe@discussions.microsoft.com> wrote in message
news:313D23C0-E3AD-42FB-A926-A50A91BB979E@microsoft.com...
> Ajay - yeah, I think either way you suggest would work OK, thanks.
>
>
>
> I'm wondering about your comment. The documentation for AfxGetMainWnd()
> says: if the function is called from a secondary thread in the application
> (which is what I'm doing), the function returns the main window associated
> with the thread that made the call. This is why AfxGetMainWnd() works
> properly with I start the thread from CMyView::OnInitalUpdate() and not
> from
> CMainFrame::OnCreate(). Are you thinking that it may not be safe to call
> it
> in any of my Worker threads?
>
>

Joe

2006-04-14, 7:09 pm

Scott - thanks for your reply. I guess it depends on where you start the
thread. When I start the thread from my View, AfxGetMainWnd() always works.
When I start it from my MainFrame, AfxGetMainWnd() always return NULL. Maybe
the difference is that the pointer has been initialized in my View, but not
in the MainFrame yet?
Joe

2006-04-14, 7:09 pm

Tom, right! I have several threads in my View and when they need to
communicate with the View they use a function that I created: CMyView*
GetView() that returns a pointer to the View. When I use GetView() and
AfxGetMainWnd() I only use it with PostMessage() and make custom messages for
communication. Yeah, SendMessage() doesn't do the trick all of the time - it
can temporarily hang my worker thread and add additional coupling that I
don't want.
Joe

2006-04-14, 7:09 pm

>
> AfxGetApp()->m_pMainWnd = this;
>

That's exactly it, thanks! When I put that just before where I spawn my
thread inside of CMainFrame::OnCreate(...) then AfxGetMainWnd() now returns
the correct pointer (in OnCreate() and in my thread). Your code just allows
me to initialize the pointer to what it should be a little sooner than it
would occur naturally. I was playing around with m_pMainWnd yesterday, but
didn't get the correct syntax/function to get it to work properly (like you
did).

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.