• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 853
  • Last Modified:

Best way to fix a blocked message pump in MFC

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
jhorstkamp
Asked:
jhorstkamp
  • 6
  • 5
1 Solution
 
jkrCommented:
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
 
jhorstkampAuthor Commented:
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
 
jkrCommented:
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
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
jhorstkampAuthor Commented:
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
 
jkrCommented:
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
 
jhorstkampAuthor Commented:
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
 
jkrCommented:
Not a CSocket either - take a look at http://msdn2.microsoft.com/en-us/library/ms737889.aspx ("Complete Server and Client Code")
0
 
jhorstkampAuthor Commented:
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
 
jkrCommented:
Not really rewriting everthing as it it is quite simple... as an alternative, you can still drain the message loop when necessary.
0
 
jhorstkampAuthor Commented:
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
 
jkrCommented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 6
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now