[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Best way to fix a blocked message pump in MFC

Posted on 2007-10-15
11
Medium Priority
?
847 Views
Last Modified: 2013-11-20
All,
I have a client server app. The client sends out a heartbeat message at user determined intervals. The problem is that at other preprogrammed times the client can go into a self test mode. Unfortunately the self test mode was written such that the windows message pump gets blocked...The server then misses its expected heartbeat messages and takes control (this is a hot standby system). I am thinking of 2 possible soulutions to this probem:
1) Add "run the message pump" code in all places where the message pump could be blocked.
2) Put the "send heartbeat" function in a thread. I like this idea the best. My question is:

Which do you guys think is the best approach?
If the thread is the best approach, how do I put a "timed" event in a thread ? ie the heartbeat thread runs continously but I only need to send the message once every n seconds.

Thanks in advance,
John
0
Comment
Question by:jhorstkamp
  • 6
  • 5
11 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 20079537
A thread indeed seems the appropriate solution here - and it would be quite simple:

DWORD WINAPI HeartbeatThreadProc(
  LPVOID lpParameter   // thread data
)
{
    while(1) {

        Sleep (5 * 1000); // sleeps 5 seconds
        SendHearbeatMessage ();
    }

    return 0;
}


// Create hearbeat thread
DWORD dwTID;

CreateThread(NULL,0,HeartbeatThreadProc,NULL,0,&dwTID);
 
0
 

Author Comment

by:jhorstkamp
ID: 20081214
Thanks jkr
I tried to create the thread somewhat differently than you outlined. I tried to run the thread from my sockets class which works but now my main view doesn't get drawn after the thread starts:
This is what I did: (I have increased points to 300)

Start the thread
void CFlareSockets::StartSendHeartbeatThread()
{
      m_hSendHeartbeatThread = (HANDLE)_beginthreadex(NULL,
                        0,
                        (PBEGINTHREADEX_THREADFUNC)SendHeartbeatThreadObject,
                        (LPVOID)this,
                        0,
                        (PBEGINTHREADEX_THREADID) &m_SendHeartbeatThreadId);

      
      if(m_hSendHeartbeatThread)
      {
            Trace("Send Heartbeat Thread launched\r\n");
      }

}

DWORD WINAPI CFlareSockets::SendHeartbeatThreadObject(LPVOID param)
{
      // use the param as the address of the object
      CFlareSockets* pto = (CFlareSockets*)param;

      // Call the member function. Since we have a
      // proper object pointer, even virtual functions
      // will be called properly

      return pto->SendHeartbeatThread();

}

DWORD CFlareSockets::SendHeartbeatThread()
{
      while(1)
      {
            Sleep(5000);
            SendHeartBeat();
      }

      return 0;
}

0
 
LVL 86

Expert Comment

by:jkr
ID: 20081260
Well, would have been nice to know that beforehand ;o)

MFC sockets rely on Windows messages also, so you either use plain sockets or have to add code to drain the message pump, e.g. by calling

void DoEvents()
{
      MSG msg;
      while   (   PeekMessage (   &msg,   NULL,   0,  0,  PM_REMOVE))
      {
            ::TranslateMessage(&msg);
            DispatchMessage     (   &msg);
      }
}

periodically.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 

Author Comment

by:jhorstkamp
ID: 20081467
Perhaps a misinterpretation...
I wrote the thread code in the sockets class AFTER you're initial reply. (Based on your idea). Maybe I was trying to be too smart <grin>.
My sockets class is derived from CAsyncSocket.
Are you saying that I should "drain the message pump" in the thread proc?
Also curions to know if _beginthreadex is correct as opposed to CreateThread or AfxBeginThread?
0
 
LVL 86

Expert Comment

by:jkr
ID: 20081526
No, not in the thread proc, that is quite likely to cause trouble (MFC is not very forgiving about message pumps in multiple threads), but in the sections where you "block" the UI handling. But anyway, why not using "plain" sockets?
0
 

Author Comment

by:jhorstkamp
ID: 20081714
What di you mean by "plain" sockets - use CSocket instead?
A little more background:
This app controls a bunch of hardware through proprietary serial interfaces. The code was written a long time ago...it gets data out of the com ports through a timer tick. The whole app is based on a few timers. I was tasked to add  hot-standby capability. 2 computers running the same app are connected in a client server config. One is primary the other is secondary. The client sends a heartbeat signal at programmed intervals to the server. If a link faiure is detected the secondary switches to primary.
CAsyncSocket seemed to be the best way to go at the time. (I had very little experience with sockets at the time)
0
 
LVL 86

Expert Comment

by:jkr
ID: 20082581
Not a CSocket either - take a look at http://msdn2.microsoft.com/en-us/library/ms737889.aspx ("Complete Server and Client Code")
0
 

Author Comment

by:jhorstkamp
ID: 20085168
Umm...are you proposing that I rewrite everything per the msdn link?
I wouldn't look forward to that <grin>...
And I don't think I have the time...
0
 
LVL 86

Expert Comment

by:jkr
ID: 20086144
Not really rewriting everthing as it it is quite simple... as an alternative, you can still drain the message loop when necessary.
0
 

Author Comment

by:jhorstkamp
ID: 20090054
So you would perhaps put the msdn transmit code in one thread and the receive code in another?
At this point draining the message pump looks easier. I may try the msdn example at a later time - I think the thread technique is a better solution but I am pressed for time.

I'm more curious to know why a class derived from CAsyncSocket apparently blocks a view class from being drawn?

I've left a lot of stuff out but this is essentially it...
CMyView::OnInitialUpdate()
{
    do init stuff
    init the hot - standby
        start the send heartbeat thread
}

I tried calling Invalidate just before starting the heartbeat thread but no luck...



0
 
LVL 86

Accepted Solution

by:
jkr earned 900 total points
ID: 20105957
No, keep all messaging in one thread. When you have time-consuming operations, the usually happen in loops, so place a call to 'DoEvents()' in them.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
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.
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…
Suggested Courses

829 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