Solved

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

Posted on 2003-10-29
10
365 Views
Last Modified: 2013-11-20
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
0
Comment
Question by:linginlondon
  • 3
  • 2
  • 2
  • +2
10 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 9640908
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
0
 

Author Comment

by:linginlondon
ID: 9641108
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()
{

}


0
 
LVL 30

Expert Comment

by:Zoppo
ID: 9641144
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
0
 
LVL 30

Accepted Solution

by:
Zoppo earned 125 total points
ID: 9641158
Sorry, I forgot to mention that you function should even
have two paramters WPARAM and LPARAM ...

Here's a link about this:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_user.2d.defined_handlers.asp

ZOPPO
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 9641209
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.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:linginlondon
ID: 9641526
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
0
 
LVL 13

Expert Comment

by:SteH
ID: 9641698
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.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 9641770
Thanks SteH.
Nice trick rather than implementing a message pump.
0
 
LVL 13

Expert Comment

by:SteH
ID: 9641804
A message pump won't work when in a different thread. It is the same as using a message pump in single threaded app.
0
 

Author Comment

by:linginlondon
ID: 9642532
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...
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
GIF file bit manipulation for color change 5 104
Host to IP 7 73
notReplace  challenge 53 102
zeroFront challenge 7 71
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now