Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Facebook Sign In with Google Sign In with OpenID

Categories

We have migrated to a new platform! Please note that you will need to reset your password to log in (your credentials are still in-tact though). Please contact lee@programmersheaven.com if you have questions.
Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

threads.. a beginner's agony..

artheaarthea Posts: 2Member
I need to create a new thread to run program in a subDialog box.
The subDialog is a drawing function that consists of a self-defined drawing requirement and an on-paint function that initialize the self function. This subDialog calls on variables from the Main dialog to see how many objects it needs to draw.
Effect: When the Main Prog runs real-time, the sub Prog will show the number of objects simultanously.

So, in creating a thread in the main dialog, how do you create a pointer to point back the subDialog class to the main Dialog?
What do you write for the source code?
«1

Comments

  • DB1DB1 Posts: 1,142Member
    : I need to create a new thread to run program in a subDialog box.
    : The subDialog is a drawing function that consists of a self-defined drawing requirement and an on-paint function that initialize the self function. This subDialog calls on variables from the Main dialog to see how many objects it needs to draw.
    : Effect: When the Main Prog runs real-time, the sub Prog will show the number of objects simultanously.
    :
    : So, in creating a thread in the main dialog, how do you create a pointer to point back the subDialog class to the main Dialog?
    : What do you write for the source code?
    :

    There's a few ways you can do that. One way would be to get a CWnd to the main window and use that to access the main dialog..
    [code]
    [green]// in ThreadProc[/green]
    CWnd *CWndParent = AfxGetMainWnd();
    [green]// or[/green]
    CWnd *CWndParent = GetParent();

    ((CMyMainDialog*)CWndParent)->DoSomething();
    [/code]
    Or the way I would do it is to pass the main dialogs CWnd to the new thread via the CreateThread's lpParameter, then I can use it in the thread.
    [code]
    CWinThread *pThread = AfxBeginThread(ThreadProc, (LPVOID)[blue]this[/blue], THREAD_PRIORITY_NORMAL);
    [green]// or[/green]
    HANDLE pThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)[blue]this[/blue], 0, &pThreadID);

    [green]// in ThreadProc[/green]
    CWnd *CWndParent = (CWnd*)lpParam;
    ((CMyMainDialog*)CWndParent)->DoSomething();
    [/code]


    [italic][blue]To understand recursive, first you need to understand recursive[/blue][/italic]

  • suhredayansuhredayan Posts: 69Member
    [b][red]This message was edited by suhredayan at 2004-2-10 6:5:57[/red][/b][hr]

    You cannot pass a CWnd object pointer like this between threads. Instead you have to pass the window handle , from which a pointer to the original object can be reconstructed using the static
    CWnd::FromHandle function;

    eg :
    [code]
    UINT int thread_func (void *arg)
    {
    HWND hwnd = (HWND)arg;
    CWnd *pWnd = CWnd::FromHandle (hwnd);
    // proceed to use pWnd..
    }
    [/code]


    greatest thing is to do wot others think you can't..
    suhredayan@omniquad.com



  • dwccgcdwccgc Posts: 576Member
    What's wrong with this. It has always worked for me.
    [code]
    void CMyView::StartThread()
    {
    AfxBeginThread(MyThread, this, THREAD_PRIORITY_BELOW_NORMAL);
    return;
    }

    UINT MyThread(LPVOID pParam)
    {
    CMyView *pMyView = (CMyView *) pParam;
    [b]
    ...
    ...
    ...
    [/b]
    return 0;
    }
    [/code]

    : [b][red]This message was edited by suhredayan at 2004-2-10 6:5:57[/red][/b][hr]
    :
    : You cannot pass a CWnd object pointer like this between threads. Instead you have to pass the window handle , from which a pointer to the original object can be reconstructed using the static
    : CWnd::FromHandle function;
    :
    : eg :
    : [code]
    : UINT int thread_func (void *arg)
    : {
    : HWND hwnd = (HWND)arg;
    : CWnd *pWnd = CWnd::FromHandle (hwnd);
    : // proceed to use pWnd..
    : }
    : [/code]
    :
    :
    : greatest thing is to do wot others think you can't..
    : suhredayan@omniquad.com
    :
    :
    :
    :

  • suhredayansuhredayan Posts: 69Member

    [blue]
    You're breaking a cardinal rule of MFC: Don't pass CWnd objects between
    threads. The fact that the code happens to work is a fluke. More
    complicated code would definitely be hitting asserts all over the place.
    [/blue]
    __________________________________________
    [red]greatest thing is to do wot others think you can't..
    suhredayan@omniquad.com[/red]

  • DB1DB1 Posts: 1,142Member
    :
    : [blue]
    : You're breaking a cardinal rule of MFC: Don't pass CWnd objects between
    : threads. The fact that the code happens to work is a fluke. More
    : complicated code would definitely be hitting asserts all over the place.
    : [/blue]
    : __________________________________________
    : [red]greatest thing is to do wot others think you can't..
    : suhredayan@omniquad.com[/red]
    :
    :

    Ahh yes, thanks for correcting me. MSDN Technical Note TN003 (Mapping of Windows Handles to Objects) explains it very well.


    [italic][blue]To understand recursive, first you need to understand recursive[/blue][/italic]

  • stoberstober Posts: 9,765Member ✭✭✭
    : :
    : : [blue]
    : : You're breaking a cardinal rule of MFC: Don't pass CWnd objects between
    : : threads. The fact that the code happens to work is a fluke. More
    : : complicated code would definitely be hitting asserts all over the place.
    : : [/blue]
    : : __________________________________________
    : : [red]greatest thing is to do wot others think you can't..
    : : suhredayan@omniquad.com[/red]
    : :
    : :
    :
    : Ahh yes, thanks for correcting me. MSDN Technical Note TN003 (Mapping of Windows Handles to Objects) explains it very well.
    :
    :
    : [italic][blue]To understand recursive, first you need to understand recursive[/blue][/italic]
    :
    :

    The way I do that is to send private messages from thread 2 to its parent thread and let the parent thread update the window, or dialog, or whatever. My program crashed bigtime the first time I attempted to update a dialog in thread #2.

  • DB1DB1 Posts: 1,142Member
    : : :
    : : : [blue]
    : : : You're breaking a cardinal rule of MFC: Don't pass CWnd objects between
    : : : threads. The fact that the code happens to work is a fluke. More
    : : : complicated code would definitely be hitting asserts all over the place.
    : : : [/blue]
    : : : __________________________________________
    : : : [red]greatest thing is to do wot others think you can't..
    : : : suhredayan@omniquad.com[/red]
    : : :
    : : :
    : :
    : : Ahh yes, thanks for correcting me. MSDN Technical Note TN003 (Mapping of Windows Handles to Objects) explains it very well.
    : :
    : :
    : : [italic][blue]To understand recursive, first you need to understand recursive[/blue][/italic]
    : :
    : :
    :
    : The way I do that is to send private messages from thread 2 to its parent thread and let the parent thread update the window, or dialog, or whatever. My program crashed bigtime the first time I attempted to update a dialog in thread #2.
    :
    :


    Ok here's what I'm doing..
    I'm creating a new thread and passing it the main Dialog's 'm_hWnd' member. In the new thread, I'm creating a new CWnd object using CWnd::FromHandle() on the HWND I passed to it. When I want to notify the main dialog of something, I use MyNewCWnd->PostMessage() with a user-defined message and a user-defined message handler in the main thread to handle it.

    Now, if MyNewCWnd->PostMessage() works fine, shouldn't I also be able to call a function directly.. ex: MyNewCWnd->SomeFunction(); or should I only stick to using PostMessage()?




    [italic][blue]To understand recursive, first you need to understand recursive[/blue][/italic]

  • suhredayansuhredayan Posts: 69Member
    : : : :
    : : : : [blue]
    : : : : You're breaking a cardinal rule of MFC: Don't pass CWnd objects between
    : : : : threads. The fact that the code happens to work is a fluke. More
    : : : : complicated code would definitely be hitting asserts all over the place.
    : : : : [/blue]
    : : : : __________________________________________
    : : : : [red]greatest thing is to do wot others think you can't..
    : : : : suhredayan@omniquad.com[/red]
    : : : :
    : : : :
    : : :
    : : : Ahh yes, thanks for correcting me. MSDN Technical Note TN003 (Mapping of Windows Handles to Objects) explains it very well.
    : : :
    : : :
    : : : [italic][blue]To understand recursive, first you need to understand recursive[/blue][/italic]
    : : :
    : : :
    : :
    : : The way I do that is to send private messages from thread 2 to its parent thread and let the parent thread update the window, or dialog, or whatever. My program crashed bigtime the first time I attempted to update a dialog in thread #2.
    : :
    : :
    :
    :
    : Ok here's what I'm doing..
    : I'm creating a new thread and passing it the main Dialog's 'm_hWnd' member. In the new thread, I'm creating a new CWnd object using CWnd::FromHandle() on the HWND I passed to it. When I want to notify the main dialog of something, I use MyNewCWnd->PostMessage() with a user-defined message and a user-defined message handler in the main thread to handle it.
    :
    : Now, if MyNewCWnd->PostMessage() works fine, shouldn't I also be able to call a function directly.. ex: MyNewCWnd->SomeFunction(); or should I only stick to using PostMessage()?
    :
    :
    :
    :
    : [italic][blue]To understand recursive, first you need to understand recursive[/blue][/italic]
    :
    :
    [blue]
    The object maps are thread-local. ie, if you are in a thread and do a CWnd::FromHandle you will get a new, temporary window object which is not the same C++ object that represented your class initially. Thus this is always fatal in a thread.

    instead u can use
    CMyWindowClass * me =
    (CMyWindowClass *)CWnd::FromHandlePermanent(hWnd);
    to get the permanent handle. [red]But only if you actually created the window in that UI-thread itself[/red].

    so i feel its better to use stober's idea of sending private messages to the parent thread
    [/blue]

    __________________________________________
    [red]greatest thing is to do wot others think you can't..
    suhredayan@omniquad.com[/red]

  • DB1DB1 Posts: 1,142Member
    : : : The way I do that is to send private messages from thread 2 to its parent thread and let the parent thread update the window, or dialog, or whatever. My program crashed bigtime the first time I attempted to update a dialog in thread #2.
    : : :
    : : :
    : :
    : :
    : : Ok here's what I'm doing..
    : : I'm creating a new thread and passing it the main Dialog's 'm_hWnd' member. In the new thread, I'm creating a new CWnd object using CWnd::FromHandle() on the HWND I passed to it. When I want to notify the main dialog of something, I use MyNewCWnd->PostMessage() with a user-defined message and a user-defined message handler in the main thread to handle it.
    : :
    : : Now, if MyNewCWnd->PostMessage() works fine, shouldn't I also be able to call a function directly.. ex: MyNewCWnd->SomeFunction(); or should I only stick to using PostMessage()?
    : :
    : :
    : :
    : :
    : : [italic][blue]To understand recursive, first you need to understand recursive[/blue][/italic]
    : :
    : :
    : [blue]
    : The object maps are thread-local. ie, if you are in a thread and do a CWnd::FromHandle you will get a new, temporary window object which is not the same C++ object that represented your class initially. Thus this is always fatal in a thread.
    :
    : instead u can use
    : CMyWindowClass * me =
    : (CMyWindowClass *)CWnd::FromHandlePermanent(hWnd);
    : to get the permanent handle. [red]But only if you actually created the window in that UI-thread itself[/red].
    :
    : so i feel its better to use stober's idea of sending private messages to the parent thread
    : [/blue]
    :
    : __________________________________________
    : [red]greatest thing is to do wot others think you can't..
    : suhredayan@omniquad.com[/red]
    :
    :



    I'm thinking it's best to simply pass the new thread the main window's m_hWnd, and in the thread use ::PostMessage((HWND)lpParam, WM_SOME_MESSAGE);

    What method of sending 'private messges' do you use Stober?





    [italic][blue]To understand recursive, first you need to understand recursive[/blue][/italic]

  • stoberstober Posts: 9,765Member ✭✭✭
    [b][red]This message was edited by stober at 2004-2-13 4:52:25[/red][/b][hr]
    :
    : What method of sending 'private messges' do you use Stober?
    :

    I use CreateThread() to create thread #2. The 4th parameter ("ThreadParameter") is the current thread ID obtained by calling GetCurrentThreadId().

    The new thread calls PostThreadMessage() with the parent's threadID from the thread's argument.


«1
Sign In or Register to comment.