Delphi 11 Alexandria:TIdHTTPServer的OnCommandGet事件通知异常
关于TIdHTTPServer OnCommandGet事件中本地通知调用失败的问题解决
问题场景
搭建XmlRpc服务器时,通过TIdHTTPServer的OnCommandGet事件处理接收的命令,命令分发正常,但通知展示步骤失败。
相关代码
服务器初始化代码
FServer := TIdHTTPServer.Create(nil); FServer.DefaultPort := StrToInt(Uri4port.port); FServer.OnCommandGet := FServerCommandGet;
通知处理函数
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;
异常信息
调试输出:
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.
英文释义:
application called an interface kept in state for a different thread
已验证:通知序列在独立环境中可正常运行,不含通知的完整流程也能正常工作。
问题原因
TIdHTTPServer的OnCommandGet事件在工作线程中触发,而本地通知(TNotification相关API)属于UI交互类操作,要求必须在主线程执行。跨线程调用UI相关接口会触发线程上下文不匹配的COM异常(错误码8001010E)。
解决方法
将通知调用同步到主线程执行,修改调用逻辑如下:
TH1 := MainThreadID; TH2 := GetCurrentThreadId; NeedSync := not(TH1=TH2); If NeedSync then TThread.Synchronize(nil, procedure begin SampNotify(Lib); end) else SampNotify(Lib);
该逻辑会判断当前线程是否为主线程,若非主线程则通过TThread.Synchronize将通知操作同步到主线程执行,避免线程上下文冲突。
内容的提问来源于stack exchange,提问作者Jean-Paul
相关产品推荐
相关产品推荐

