Thread: problem calling a function from a thread

  1. #1
    Registered User
    Join Date
    Oct 2003
    Posts
    106

    problem calling a function from a thread

    Hello, I need help about this thing. For shure this have been seen many times but I just can't find the keywords to search about....:P Here is the problem:

    I have a CDialog derived window with a "privExecCommand( CHAR cmd )" function that I placed in the class. Now, I started a worker thread (without GUI ) to receive commands from serial port. This thread the wants to send the commands to the main window calling that function. Let's say:
    Code:
    class CMyDlg : public CDialog
    {
    ....
    private:
    	void privExecCommand( CHAR cmd );
            static INT privListeningThread( LPVOID pParams );
    ....
    }
    
    BOOL CMyDlg::OnInitDialog()
    {
    ....
            AfxBeginThread( (AFX_THREADPROC) privListeningThread, (LPVOID)(this) );
    ....
    }
    
    
    INT CMyDlg::privListeningThread(LPVOID pParams)
    {
    ....
            CMyDlg *pCaller = (CMyDlg*) pParams;
    ....
            pCaller->privExecCommand( cmd );
    }
    Now, it happens that pCaller is really the pointer to the main object, because some functions that do not access to the members but just draw on the GUI, do work. Else, when I call the "privExecCommand( cmd )" function, the fields of the called object are....new, empy, different from the real object.

    Why does this happen? Thank you for any hint.

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    UINT __cdecl MyControllingFunction( LPVOID pParam );

    INT privListeningThread( LPVOID pParams );

    Don't you see any difference?

    you have changed UINT to INT (small problem) and have missed __cdecl calling conventions - big problem. Your function has not the type of calling convensions that AfxBeginThread expects, so it interprets stack in a wrong way
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    This is really a really bad thing to do. Either make a static function, use a global-level function (both as wrappers) or use some neat template code that I have to automatically call your class member function.
    And don't cast the function address. And do
    Code:
    &CMyDlg::privListeningThread
    too. Just privListeningThread isn't standard, AFAIK.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Registered User
    Join Date
    Oct 2003
    Posts
    106
    I did everything you suggested, but doesn't work...now this is the current situation:
    Code:
    class CMyDlg : public CDialog
    {
    ....
    private:
        void privExecCommand( CHAR cmd );
        static UINT __cdecl privListeningThread( LPVOID pParams );
    ....
    }
    
    BOOL CMyDlg::OnInitDialog()
    {
    ....
        AfxBeginThread( (AFX_THREADPROC) &CMyDlg::privListeningThread, (LPVOID)(this) );
    ....
    }
    
    
    UINT CMyDlg::privListeningThread(LPVOID pParams)
    {
    ....
        CMyDlg *pCaller = (CMyDlg*) pParams;
        do{
             .......
             cmd = foo_ReadPort();
             pCaller->privExecCommand( cmd );
             .......
        }while( TRUE );
        return 0;
    }
    It still happens that the method called can't find the right members of the object called, insted it finds zeroed fileds.
    I'm using VC++ 6.0

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Remove that cast. If it doesn't compile without it, then your prototype function is wrong.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User
    Join Date
    Oct 2003
    Posts
    106
    First, thank you to keep going on helping me^^.
    Removing the cast didn't change the situation: the compiler doesn't comply, and compiles without warnings. The called functions still can't access to the custom dialog fileds. It's like if it's called a method of an uninitialized CMyDlg object.

    Everything works if I use
    Code:
    pCaller->SendMessage( WM_CUSTOMMESSAGE_RECEIVED_CHAR , (WPARAM)cmd)
    and place a message handler to send the received byte to my privExecuteCommand() function. But I'd like to avoid this, it seems....slow.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    There may be some additional problem that's not stemming from your thread or function call. Something else might be modifying data before your thread accesses it, perhaps?
    Maybe you should provide further insight on your code.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Oct 2003
    Posts
    106
    Thank you Elysia, I'll keep trying, it's important enough that the call from the thread to the class's method it's ok now, so it can be excluded. I'll let you know :-)

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You cannot call any function from a thread in MFC that accesses the GUI. If you need any access to the GUI from a thread you must derive a class from CThread.

    Now your worker thread can alter variables related to the GUI and after it terminates you are free to update the GUI. However even though you are not truly calling the GUI from your thread you are still calling a function that accesses the GUI.

    If this is what is happening then your GUI will deadlock until the thread completes. It was a little difficult understanding your exact problem so forgive me if this is not it.

    Remember that a worker thread can never touch the GUI. This also means that your thread cannot call Control.Invalidate(). I had a similar problem trying to get a progress bar to update while parsing a file. Eventually I had to derive my class from CThread and all worked well.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  2. Replies: 6
    Last Post: 03-02-2005, 02:45 AM
  3. problem getting result when calling a function
    By drb2k2 in forum Windows Programming
    Replies: 1
    Last Post: 04-14-2003, 09:51 AM
  4. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM
  5. qt help
    By Unregistered in forum Linux Programming
    Replies: 1
    Last Post: 04-20-2002, 09:51 AM