zoukankan      html  css  js  c++  java
  • You should not be calling AfxGetMainWnd in a worker thread

    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).
  • 相关阅读:
    Python如何编写一个带命令行参数的程序
    软件工程第二次作业----(1)补交
    软件工程第二次作业----
    2017软件工程第一次作业
    2017软件工程第三次作业--功能测试
    2017软件工程第三次作业--效能分析
    每周例行报告
    2017软件工程第二次作业(一)
    2017软件工程第二次作业(二)
    2017软件工程第一次作业
  • 原文地址:https://www.cnblogs.com/cy163/p/550339.html
Copyright © 2011-2022 走看看