Delphi XE5 Android Indy TIDNotify未执行
我已经将代码简化为一个简单的示例。Delphi XE5 Android Indy TIDNotify未执行,android,delphi,indy,firemonkey,delphi-xe5,Android,Delphi,Indy,Firemonkey,Delphi Xe5,我已经将代码简化为一个简单的示例。 IdTCPClient读取消息并将其显示在备忘录中。 附加的代码在Windows上运行良好,但是如果从ThC\u Receive调用PostLog,则不会在android上执行DoNotify。如果我通过按钮调用PostLog。单击main表单中的,它将被执行。 有什么建议吗? TIdSync可以工作,但建议使用它吗 unit HeaderFooterTemplate; interface uses System.SysUtils, System.Ty
IdTCPClient
读取消息并将其显示在备忘录中。
附加的代码在Windows上运行良好,但是如果从ThC\u Receive
调用PostLog
,则不会在android上执行DoNotify
。如果我通过按钮调用PostLog。单击main表单中的
,它将被执行。
有什么建议吗?
TIdSync可以工作,但建议使用它吗
unit HeaderFooterTemplate;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, IdContext, IdSync,
FMX.Layouts, FMX.Memo, IdThreadComponent, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, IdGlobal;
type
// ---------------------------------------------------------------------------
TLog = class(TIdNotify)
protected
fMsg: String;
procedure DoNotify; override;
//procedure DoSynchronize; override;
public
class procedure PostLog(const S: String);
end;
// ---------------------------------------------------------------------------
THeaderFooterForm = class(TForm)
Header: TToolBar;
Footer: TToolBar;
HeaderLabel: TLabel;
M_Log: TMemo;
IdTCPClient1: TIdTCPClient;
ThC_Receive: TIdThreadComponent;
Button2: TButton;
procedure Button2Click(Sender: TObject);
procedure IdTCPClient1Connected(Sender: TObject);
procedure ThC_ReceiveRun(Sender: TIdThreadComponent);
private
{ Private declarations }
public
{ Public declarations }
end;
var
HeaderFooterForm: THeaderFooterForm;
implementation
{$R *.fmx}
// -----------------------------------------------------------------------------
{ TLog }
// -----------------------------------------------------------------------------
procedure TLog.DoNotify;
begin
HeaderFooterForm.M_Log.Lines.Append(fMsg);
end;
// -----------------------------------------------------------------------------
class procedure TLog.PostLog(const S: String);
begin
with Create do
begin
try
fMsg := S;
Notify;
except
Free;
Raise;
end;
end;
end;
// -----------------------------------------------------------------------------
procedure THeaderFooterForm.Button2Click(Sender: TObject);
begin
try
IdTCPClient1.Host :='192.168.1.12';
IdTCPClient1.Port := 1001;
IdTCPClient1.Connect;
except
on E: Exception do
begin
TLog.PostLog(trim(e.Message));
Raise;
end;
end;
end;
// -----------------------------------------------------------------------------
procedure THeaderFooterForm.IdTCPClient1Connected(Sender: TObject);
begin
ThC_Receive.Start;
end;
// -----------------------------------------------------------------------------
procedure THeaderFooterForm.ThC_ReceiveRun(Sender: TIdThreadComponent);
var
s: string;
begin
try
s:= (IdTCPClient1.IOHandler.ReadLn(TransmissionSeparator, IndyTextEncoding(IdTextEncodingType.encUTF16LE)));
TLog.PostLog(trim(s));
except
on E: Exception do
begin
TLog.PostLog(trim(e.Message));
Raise;
end;
end;
end;
// -----------------------------------------------------------------------------
end.
谢谢,,
Spectro在工作线程中调用时,TIdNotify
使用TThread.Queue()
和TIdSync
使用TThread.Synchronize()
,两者都通过相同的RTL队列,因此TThread.Synchronize()
不太可能工作,但TThread.Queue()
不工作。另一方面,在主线程中调用时,不使用TThread
(除非TIdNotify.mainthreausesnotify
设置为true),而是直接调用TIdNotify.DoNotify()
和TIdSync.DoSynchronize()
。如果TIdNotify
在线程中不工作,则必须中断TThread.Queue()
,这将是Embarcadero问题,而不是Indy问题
也就是说,TIdNotify
确实有逻辑在没有可用TThread.Queue()
的Delphi版本上使用TThread.Synchronize()
。您可以尝试复制IdSync.pas
并对其进行修改,以在Android上取消定义HAS\u STATIC\u TThread\u Queue
定义,然后将修改后的文件添加到项目中。不过,这仅在禁用运行时包时有效。我不是Android开发者,所以我不知道Delphi如何在移动平台上使用软件包
顺便说一句,IndyTextEncoding(idtextcodingtype.encUTF16LE)
可以替换为IndyTextEncoding\u UTF16LE
更新:FireMonkey本身已经发现了一个bug(请参阅),它可以追溯到FireMonkey首次引入的时候,并且仍然存在于XE5更新2中。简而言之,FMX.TApplication
不会将处理程序分配给System.Classes.WakeMainThread
回调(Vcl.TApplication
会)TThread
调用WakeMainThread
通知主线程一个Synchronize/Queue()
请求挂起。因此,如果在调用Synchronize/Queue()
时主消息循环处于空闲状态,则在以后的某个时间如果/当其他内容将新消息放入主消息队列时,不会发生任何事情。如果没有该选项,则不会调用TApplication.Idle()
,因此不会调用CheckSynchronize()
来处理挂起的Synchronize/Queue()
请求。这意味着对于后台/非可视进程,Synchronize/Queue()
可能根本无法正常工作,而且偶尔会在GUI进程中正常工作。在Embarcadero修复该错误之前,解决方法是将自定义消息发布到主消息队列以“唤醒”它,或者在主线程中定期手动调用CheckSynchronize()
,例如在计时器中