【问题标题】:Delphi XE5 Android Thread makes app crashDelphi XE5 Android Thread 使应用程序崩溃
【发布时间】:2014-05-05 07:51:09
【问题描述】:

我有一个线程从远程 Datasnap 服务器下载并保存 clientDataset 文件 cds 文件。

此线程适用于 Windows、IOS(模拟器、Iphone、Ipad),但不适用于 Android。

应用程序在完成文件下载并保存到 Android 后崩溃。

代码很简单。

线程:

TDownloadSaveRemoteDBThread = class (TThread)
public
  Username,Password,host,port : String;
  error                      : String;
  Folder                     : String;
  ServerMethod               : String;
  filename                   : String;
protected
  procedure Execute; override;
end;

procedure TDownloadSaveRemoteDBThread.Execute;
var
  sqlCon : TSqlConnection;
  cds    : TClientDataset;
  ssm    : TSqlServerMethod;
  dpr    : TDataSetProvider;
begin
  inherited;

  error :='';
  SqlCon:=TSQLConnection.Create(nil);
  try
    sqlCon.DriverName:='Datasnap';
    sqlCon.LoginPrompt:=false;
    sqlCon.Params.Values['hostname']:=host;
    sqlCon.Params.Values['port']:=port;
    sqlCon.Params.Values['UserName']:=Username;
    sqlCon.Params.Values['Password']:=Password;
    try
      sqlCon.Open;
      cds:=TClientDataset.Create(nil);
      ssm:=TSqlServerMethod.Create(nil);
      dpr:=TDataSetProvider.Create(nil);
      try
        ssm.SQLConnection:=SqlCon;
        ssm.ServerMethodName:=ServerMethod;
        dpr.DataSet:=ssm;
        cds.SetProvider(dpr);
        cds.Open;
        cds.SaveToFile(folder+filename);
        cds.Close;
      finally
        cds.free;
        ssm.free;
        dpr.free;
      end;
    Except
      on E : Exception do
      Begin
        error:=E.Message;
        SQLCon.Close;
      End;
    end;
  finally
    SQLCon.Close;
    SQLCon.free;
  end;
end;

我有一个按钮可以在我的主窗体“开始窗体”中启动线程

procedure TStartForm.Button1Click(Sender: TObject);
var
  DownloadSaveRemoteDBThread : TDownloadSaveRemoteDBThread;
begin
  DownloadSaveRemoteDBThread:= TDownloadSaveRemoteDBThread.Create(true);
  DownloadSaveRemoteDBThread.OnTerminate:= StartForm.ferdigHentDB;
  DownloadSaveRemoteDBThread.Password:='test';
  DownloadSaveRemoteDBThread.Username:='test';
  DownloadSaveRemoteDBThread.host:=edit1.text; //127.0.0.1
  DownloadSaveRemoteDBThread.port:='211';
  DownloadSaveRemoteDBThread.Folder:=System.IOUtils.TPath.GetDocumentsPath +  PathDelim +'db'+  PathDelim;
  DownloadSaveRemoteDBThread.ServerMethod:= 'TServerMethods2.hentselect3';
  DownloadSaveRemoteDBThread.filename:='select3.cds';
  DownloadSaveRemoteDBThread.FreeOnTerminate:=true;
  DownloadSaveRemoteDBThread.Start;
end;

然后线程完成后我有这个简单的过程

procedure TStartForm.ferdigHentDB(sender: Tobject);
begin

  with sender as TDownloadSaveRemoteDBThread do
  Begin
    if error > '' then
    Begin
      showmessage(error);
    End;
  End;
end;

关于 Android 崩溃的任何建议,是否有简单的解决方法?

【问题讨论】:

  • android版本支持多线程连接的情况下,你查看数据库驱动的文档了吗?

标签: android multithreading delphi delphi-xe5


【解决方案1】:

XE5 中的TThread 在Android 上有两个主要错误。 Sychronize()Queue() 已损坏(Synchronize() 用于触发 OnTerminate 事件),如果线程使用了任何 JNI 对象,TThread 在终止之前不会将自身与 Android JVM 分离。 The first bug 尚未修复。第二个错误在 XE6 中已修复,但在 XE5 中可以使用a workaround

【讨论】:

  • 谢谢,但我可以弄清楚如何实施修复。过程MyEndThreadProc(ExitCode:Integer); 在我的system.classes 中我发现此代码` {$ELSEIF Defined(POSIX)} if Assigned(EndThreadProc) then EndThreadProc(Result); pthread_exit(结果); {$ENDIF POSIX}` 有没有人举例说明如何在 system.classes 中分配 MyEndThreadProc
  • 我发布的链接中有什么不清楚的地方?它确切地告诉您如何实施修复。 EndThreadProc 是一个函数指针。只需将提供的函数复制到您的代码中,然后在应用程序启动时将其地址分配给System.Classes.EndThreadProc 变量。然后,每当基于TThread 的线程终止时,TThread 就会调用您的函数。
猜你喜欢
  • 2016-06-13
  • 1970-01-01
  • 2014-02-08
  • 1970-01-01
  • 2019-04-22
  • 2012-10-04
  • 1970-01-01
相关资源
最近更新 更多