troubleshooting Question

SendMessage vs PostMessage (and lost messages..)

Avatar of ahalya
ahalyaFlag for Canada asked on
DelphiMicrosoft Development
11 Comments1 Solution13110 ViewsLast Modified:
I have a thread communicating with a window via messages.

I want to use PostMessage, but for some reason I seem to lose many of the messages sent via postmessage.  This happens occasionally, and seems to be unpredictable.  

If I use SendMessage, I receive every message, but am struck if SendMessage is called while I'm waiting inside a WaitForSingleObject. (I use a semaphore and WaitForSingleObject function to determine whether the thread is active or not).

Post Message, I lose many, and it appears the MC_ThreadEnd message is lost most of the time This is the last message sent just before the thread terminates).

I have attached a sample log created from these communications to show how I track the messages. They aretimed tightly (nearest micro second in the field following :: symbol in the file)

comments, Solutions, Alternatives please.  (MY OS is XP SP2 with all patches/updates applied. Compiler Delphi 7 with all patches applied).
///////////////////////////////////////////////////////////////////
//  These two procedures process WM_Debug, & WM_Thread messages  //
///////////////////////////////////////////////////////////////////
procedure TMainForm.DebugMessages(var M: TMessage);
 
var ErrMsg: array[0..255] of char;
    StrSize: word;
 
begin;
  StrSize := GlobalGetAtomName(M.LParam, ErrMsg, 256);
  GlobalDeleteAtom(M.LParam);
  if StrSize > 0 then
  begin;
    case M.WParam of
    MC_ErrMsg:    LogInfo(nil, string(ErrMsg));
    MC_DebugMsg : LogInfo(nil, string(ErrMsg));
    MC_MutexMsg : LogInfo(nil, string(ErrMsg));
  end;
else
    TimedMessageDlg('Error message not found !', mtError,[mbOk], 0, 10, mrOk);
end;
 
 
procedure TMainForm.ThreadMessages(var M: TMessage);
 
begin;
  case M.WParam of
    MC_MotorStart : LogInfo(nil, Format('%s stepper motor started', [FeedbackChannelNames[M.LParam - md_ref+countAO]]));
    MC_MotorStop  : LogInfo(nil, Format('%s stepper motor stopped', [FeedbackChannelNames[M.LParam - md_ref+countAO]]));
 
    MC_ThreadCreate: LogInfo(nil, Format('%s. New Thread started', [GetAtomMsg]));
    MC_ThreadQuit  : LogInfo(nil, Format('%s. Thread Quit Request', [GetAtomMsg]));
    MC_ThreadProc  : LogInfo(nil, Format('%s. ThreadProc activated', [GetAtomMsg]));
    MC_ThreadInfo  : LogInfo(nil, Format('%s', [GetAtomMsg]));
    MC_ThreadEnd:
      begin;
        LogInfo(nil, Format('%s. Thread Ended', [GetAtomMsg]));
        dec(ThreadCount);
        IsMultiThread := (ThreadCount > 1);
        CloseHandle(hEPTThread);
        hEPTThread := 0;
      end;
  end;
 
  Caption := Format('HCT DAQ [%d threads active]', [ThreadCount]);
  if (M.WParam = MC_MotorStop) then DAQModule.SetCWButtonState(M.LParam, false);
  if (M.WParam = MC_MotorStart) then DAQModule.SetCWButtonState(M.LParam, true);
end;
 
/////////////////////////////////////////////////////////////////
//   Messages are sent from a separate thread. Example below   //
////////////////////////////////////////////////////////////////
 
<part of the Thread function>
 
    loop := 0; steps := 10;
    while (not TEPTTargets(Ptr^).QuitThread) and (loop < steps) do
    begin;
      updateVariables(steps - loop);//Update if EPTs active
      for EPTransducer := ep_Vert to ep_IntP do ApplyOutput(EPTransducer);
 
      PostMessage(hMainform, WM_Debug, MC_EPTMsg,  AddGlobalAtomFmt('%s <- Calling Sleep', [getPCTAsString]));
      //Break the Sleep command into 4 individual sleeps to avoid a long hang-up
      if not TEPTTargets(Ptr^).QuitThread then sleep(TEPTTargets(Ptr^).TimeDelay div 4);
      if not TEPTTargets(Ptr^).QuitThread then sleep(TEPTTargets(Ptr^).TimeDelay div 4);
      if not TEPTTargets(Ptr^).QuitThread then sleep(TEPTTargets(Ptr^).TimeDelay div 4);
      if not TEPTTargets(Ptr^).QuitThread then sleep(TEPTTargets(Ptr^).TimeDelay - (3 * TEPTTargets(Ptr^).TimeDelay div 4));
      PostMessage(hMainform, WM_Debug, MC_EPTMsg,  AddGlobalAtomFmt('%s -> Done Sleep', [getPCTAsString]));
 
      inc(loop);
    end;
  except on e:exception do
    PostMessage(hMainform, WM_Debug, MC_ErrMsg, GlobalAddAtom(pchar(E.Message)));
    end;
 
  if TEPTTargets(Ptr^).QuitThread then
     PostMessage(hMainform, WM_Thread, MC_ThreadQuit, AddGlobalAtomFmt('%s <EPT>', [getPCTAsString]));
  PostMessage(hMainform, WM_Thread, MC_ThreadEnd, AddGlobalAtomFmt('%s', [getPCTAsString]));
hct.execution.log
Join the community to see this answer!
Join our exclusive community to see this answer & millions of others.
Unlock 1 Answer and 11 Comments.
Join the Community
Learn from the best

Network and collaborate with thousands of CTOs, CISOs, and IT Pros rooting for you and your success.

Andrew Hancock - VMware vExpert
See if this solution works for you by signing up for a 7 day free trial.
Unlock 1 Answer and 11 Comments.
Try for 7 days

”The time we save is the biggest benefit of E-E to our team. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange.

-Mike Kapnisakis, Warner Bros