Search code examples
notificationsdelphi-11-alexandria

(DELPHI 11 Alexandria) Exception in Notification processing


I'm setting up an XmlRpc server. When analyzing a received command from the OnCommandGet event of a TIdHTTPServer:

FServer := TIdHTTPServer.Create(nil);
FServer.DefaultPort := StrToInt(Uri4port.port);
FServer.OnCommandGet := FServerCommandGet;

The command dispatch is OK, But the Notification process fails at the Presentation step:

function CmdReceived_Decod.SampNotify(Lib: String): Boolean;
var
  S: String;
  now1: String;
  MyNotification: TNotification;
begin
  Now1 := DateTimeToStr(Now, AFormatSettings);
  if not Assigned(MyNotifCenter) then MyNotifCenter.Create(nil);
  Inc(Cpt_Notif);
  MyNotifCenter.CancelAll;
  //
  MyNotification := MyNotifCenter.CreateNotification;
  MyNotification.Name:= C_NomNotif + now1; // Nom Unique
  MyNotification.AlertBody := lib;
  MyNotification.Title := C_NotifTitle;
  MyNotification.Number := Cpt_Notif;
  MyNotification.FireDate := Now;
  MyMsgBox(lib, 'Samp_Vo', MB_OK);
     
  try
    Result := false;
    MyNotifCenter.PresentNotification(MyNotification);
  except
    on E: ELocalNotificationAccess do
      ShowMessage('Exception Type: ' + E.ClassName + ' =>  ' + E.Message);
    on E: Exception do
      WriteLn(E.Message);
  end;
  Result := true;
end;

The Exception message is:

" Sortie de débogage:
onecore\com\combase\dcomrem\channelb.cxx(6563)\combase.dll!7688696F: (caller: 751C64A4) ReturnHr(1) tid(eb0) 8001010E L’application a appelé une interface qui était maintenue en ordre pour un thread différent."

In English : "application called an interface kept in state for a different thread"

I closely verified that the notify sequence works in a standalone environnement, and that the full process worked without notifications.

Are notifications prohibited in the OnCommandGet event?

How to work around this?


UPDATE:

According to the given answer, the call is successfully modified as:

TH1 := MainThreadID; 
TH2 := GetCurrentThreadId;
NeedSync := not(TH1=TH2);
If NeedSync then
  TThread.Synchronize(nil, procedure begin 
    SampNotify(Lib); end)
else SampNotify(Lib);

Solution

  • Check from which thread SampNotify() is called. Probably this is not the main thread. You can get the current thread ID using with GetCurrentThreadId, and the main thread ID with MainThreadID. If the code is indeed running on a separate thread, synchronizing the call to SampNotify() might solve this problem:

    You can do something like this:

    TThread.Synchronize(nil, procedure begin SampNotify(); end);