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);
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);