threads.. a beginner's agony..

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

  • : 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]

  • [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..
    [email protected]



  • 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..
    : [email protected]
    :
    :
    :
    :


  • [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..
    [email protected][/red]

  • :
    : [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..
    : [email protected][/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]

  • : :
    : : [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..
    : : [email protected][/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.

  • : : :
    : : : [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..
    : : : [email protected][/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]
    : : : : 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..
    : : : : [email protected][/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..
    [email protected][/red]

  • : : : 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..
    : [email protected][/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]

  • [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.


  • :
    : 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.
    :

    [blue]
    Be carefule that MFC will not dispatch PostThreadMessage() to message or command handlers.You will have to override PreTranslateMessage() function of your CWinApp-derived class.
    [red]
    Also Messages sent to a UI thread through PostThreadMessage will be lost [/red] if the messages are posted while the user is manipulating a window owned by the thread.So Rather than using PostThreadMessage to post messages to a UI thread, use PostMessage to post messages to a window owned by that thread.
    [/blue]

    __________________________________________
    [red]greatest thing is to do wot others think you can't..
    [email protected][/red]

  • : :
    : : 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.
    : :
    :
    : [blue]
    : Be carefule that MFC will not dispatch PostThreadMessage() to message or command handlers.You will have to override PreTranslateMessage() function of your CWinApp-derived class.
    : [red]
    : Also Messages sent to a UI thread through PostThreadMessage will be lost [/red] if the messages are posted while the user is manipulating a window owned by the thread.So Rather than using PostThreadMessage to post messages to a UI thread, use PostMessage to post messages to a window owned by that thread.
    : [/blue]
    :

    The parent thread catches the message in PreTranslateMessage() and then reposts with PostMessage() or takes other appropriate action
  • :
    : The parent thread catches the message in PreTranslateMessage() and then reposts with PostMessage() or takes other appropriate action
    :

    [blue]
    But stober still the threat of loosing the message is there b'coz its send to a user interface thread using PostThreadMessage().
    [red](Ref : MSDN ->ID: Q183116) [/red]
    Wot about sending the message directly to the window of the main thread using PostMessage() function ..
    [/blue]
    [email protected]
    __________________________________________
    [red]greatest thing is to do wot others think you can't..
    [/red]

  • :
    : [blue]
    : But stober still the threat of loosing the message is there b'coz its send to a user interface thread using PostThreadMessage().
    : [red](Ref : MSDN ->ID: Q183116) [/red]
    : Wot about sending the message directly to the window of the main thread using PostMessage() function ..
    : [/blue]


    I'm sending it to CWinApp-derived class, which is not a window.

    Here are some additional thoughts on this: And read the reader's comments at the end of the article.

    http://www.codeproject.com/tips/gbTestSDI.asp#xx718454xx

    and here is another, better article
    http://www.codeguru.com/misc/lenop.html
  • I haven't been following this conversation completely, but I thought I would try to give a suggestion. I have a CFormView which executes a thread every minute. If a certain situation occurs, I update a text box on the CFormView. Here is how I do it.

    Thread that will post a message to CMainFrame
    [code]
    UINT MyThread(LPVOID pParam)
    {
    ::PostMessage(AfxGetMainWnd()->m_hWnd, WM_MY_MSG, NULL, pParam);
    return 0;
    }
    [/code]


    Thread that will post a message to CFormView
    [code]
    LRESULT CMainFrame::OnMyMsg(WPARAM wParam, LPARAM lParam)
    {
    GetActiveView()->PostMessage(WM_MY_MSG, wParam, lParam);
    return 0;
    }
    [/code]

    CFormView
    [code]
    LRESULT CMyFormView::OnMyMsg(WPARAM wParam, LPARAM lParam)
    {
    // Update text box
    ....
    ....
    ....
    return 0
    }
    [/code]

    I hope this helps. If not, just ignore me.:-)




    : :
    : : [blue]
    : : But stober still the threat of loosing the message is there b'coz its send to a user interface thread using PostThreadMessage().
    : : [red](Ref : MSDN ->ID: Q183116) [/red]
    : : Wot about sending the message directly to the window of the main thread using PostMessage() function ..
    : : [/blue]
    :
    :
    : I'm sending it to CWinApp-derived class, which is not a window.
    :
    : Here are some additional thoughts on this: And read the reader's comments at the end of the article.
    :
    : http://www.codeproject.com/tips/gbTestSDI.asp#xx718454xx
    :
    : and here is another, better article
    : http://www.codeguru.com/misc/lenop.html
    :

Sign In or Register to comment.

Howdy, Stranger!

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

Categories