Link to home
Start Free TrialLog in
Avatar of linginlondon
linginlondon

asked on

Problem with Work Threads and MFC MDI App, debug vs release

Hi,

I have an MDI App, which was generated using the Visual Studio V6.0 Wizard.
I create a doc/view template and in the doc I create a 'simple' worker thread. When this thread has done some processing, it does a PostMessage to the main UI thread/view.
I use CCriticalSection around a buffer which is shared between the 2 threads.

Under both debug and release mode this works fine and the view does some UI updating from the work thread. However in release mode, if the main app gets any other windows message, eg app losses focus. It crashes. Under debug this is fine.
If I remove the PostMessage call then no crash. If I remove the code inside the handler to the PostMessage, then still crash, dispite the handler getting the message.

Does anyone have any suggestions as to what maybe wrong?

Thanks,

Ling
Avatar of AlexFM
AlexFM

Please show your code: starting the worker thread, worker thread code and handling the message.
You can also try to solve the problem debugging the Release configuration as described here:

http://www.codeguru.com/debug/release_ver.shtml
Avatar of linginlondon

ASKER

Here is some code snippets:

// create the log view thread object      
      CWinThread* pWinThread = AfxBeginThread(StartTail, reinterpret_cast<LPVOID>(this),
            THREAD_PRIORITY_NORMAL, 0, 0, NULL);

// thread code
UINT CLogDoc::StartTail(LPVOID pParam)
{

// read in data ...
..
CWnd* pWnd = (CWnd *)CWnd::FromHandle(pParam->m_pLogViewHwnd);
PostMessage(pParam, WM_USER+1000, (WPARAM)0, (LPARAM)0);
Sleep(0);
}

// in message map
ON_MESSAGE(WM_USER+1000, OnLogItemReady)
// handler code
void CEditLogView::OnLogItemReady()
{

}


Avatar of Zoppo
Hi linginlondon,

IMO problem is that your message handler function is defined wrong.
Functions which should be used with ON_MESSAGE macro must be
declared as
afx_msg LRESULT memberFxn(WPARAM, LPARAM);
You're function is declared to return 'void' instead of 'LRESULT'.

Unfortunateley I still don't know how MFC manages to work fine with
this in DEBUG mode but I know it's a common problem (coz the same
happened to me some time ago and I needed some days to figure it out).

Hope that helps,

ZOPPO
ASKER CERTIFIED SOLUTION
Avatar of Zoppo
Zoppo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
It may be better to use the SDK PostMessage fn
instead of
UINT CLogDoc::StartTail(LPVOID pParam)
{

// read in data ...
..
CWnd* pWnd = (CWnd *)CWnd::FromHandle(pParam->m_pLogViewHwnd);
PostMessage(pParam, WM_USER+1000, (WPARAM)0, (LPARAM)0);
Sleep(0);
}

use
UINT CLogDoc::StartTail(LPVOID pParam)
{

// read in data ...
..
::PostMessage(pParam->m_pLogViewHwnd, pParam, WM_USER+1000, (WPARAM)0, (LPARAM)0);
Sleep(0);
}


Also why do you have a Sleep(0); after the postmessage?  Do you want your app to do something before the thread continues?  If so use SendMessage instead of PostMessage as that wont return until the recipient finishes the processing the message.
Hi Zoppo,

Thanks for you advice, that did the trick. I've just spent the last 2days looking at all the threading code, and it was just a plain error with the function handler definition! Grrr...teach me for using cut and paste coding!

Ling
Have you tried going to WM_APP instead of WM_USER as base for the message? The range WM_USER to WM_APP is used by MS as well and might interfere.

@AndyAinscow
The Sleep (0) allows the other threads to do message processing; For example the one you just sent. If the worker thread is loading the CPU you would see nothing otherwise. All messages would be handled when the worker thread ends. SendMessage might result in a deadlock. Here the worst case would be that the message doesn't get handled immediatly.
Thanks SteH.
Nice trick rather than implementing a message pump.
A message pump won't work when in a different thread. It is the same as using a message pump in single threaded app.
Instead of using WM_USER or WM_APP one could use:
UNIT UWM_MY_UNIQUE_MSG = ::RegisterWindowMessage("Some unique string");

SteH is right on the Sleep(0) - this causes the current thread to give up it's remaining processor time and allows other threads to do some work....In my case after posting message, there was no other immediate need for the thread to hold on to the cpu...