首页 > 解决方案 > Firemonkey外部异常与Android上的线程和记录

问题描述

使用 Firemonkey 10.4.2(与 10.4.1 相同)我有很多错误,如下所示:

外部异常 1 地址:$0000007FF99E60D0

调用堆栈:libMyApp.so $00000074942D3B64 Grijjy.Errorreporting.TgoExceptionReporter.GlobalGetExceptionStackInfo(TExceptionRecord*)

  • 124 libMyApp.so $0000007493A42480 Sysutils.Exception.RaisingException(TExceptionRecord*) + 52 libMyApp.so $0000007493A6D5B4 Sysutils.RaiseExceptObject(TExceptionRecord*) + 64 libMyApp.so $0000007493A227D0 _RaiseAtExcept(TObject*, Pointer) + 64 libMyApp.so $0000007493A4164C Internal.Excutils.SignalConverter(NativeUInt, NativeUInt, NativeUInt) + 36 libMyApp.so $00000074942CE0BC Pebble.Thread.TPebbleThread_Execute_ActRec._0_Body() + 1328 libMyApp.so $00000074942CE0BC Pebble.Thread.TPebbleThread_Execute_ActRec._0_Body() +132

为了在 MapView 上加载标记,我使用了一个将 FreeOnTerminate 设置为 False 的线程。

TPebbleThread = class(TThread)
strict private
  FMapView: TMapView;
  FListMarker: TListCustomMapMarker;
  FLatitude: Double;
  FLongitude: Double;
  FShowMapViewAtEnd: boolean;
  FImgList: TImageList;
  FIsTerminate: boolean;
  FForceShowAllPebble: boolean;
  FCheckDuplicate: boolean;
public
  constructor Create(aMapView: TMapView; aListMarker: TListCustomMapMarker; aLatitude, aLongitude: Double);
  destructor Destroy; override;
  procedure Execute; override;
end;

该线程包含一些属性。

TListCustomMapMarker = class(TObjectList<TCustomMapMarker>)
  // ...
end

TCustomMapMarker = class
strict private
  FMarker: TMapMarker; // record in FMX.Maps
  FId: integer;
  FCreated: string;
  FAdded: string;
  FUser: string;
  FKm: string;
  FComment: string;
  FOwner: string;
  FFixed: boolean;
public
  constructor Create;
  destructor Destroy; override;
  // property
end;

我用try..except包围了execute方法。我看到了一些我修复的错误,但这些异常并没有出现在我的异常中。

这就像异常首先被引发(可能是我第二次调用它的时候?)

在我的主窗体上,我用我的线程加载地图:

procedure TfrmMain.LoadMapMarker;
begin
  if Assigned(FPebbleThread) then
  begin
    FPebbleThread.Terminate;
  end;

  FListMarker.RemoveMapMarker;

  FPebbleThread := TPebbleThread.Create(FListMarker, ...);
end;

完整的线程方法如下:

procedure TPebbleThread.Execute;
var
  Url            : string;
  i              : integer;
  HTTPResponse   : TToolHTTPResponse;
  Value          : TJSONValue;
  Ar             : TJSONArray;
  LatitudeDouble : Double;
  LongitudeDouble: Double;
  Latitude       : string;
  Longitude      : string;
  CustomMapMarker: TCustomMapMarker;
  Id             : integer;
  Param          : TMultipartFormData;
begin
  inherited;
  FIsTerminate := False;
  try
    Param := TMultipartFormData.Create;
    try
      Param.AddField('latitude',  FLatitude.ToString);
      Param.AddField('longitude', FLongitude.ToString);

      Param.AddField('filter', 'on');

      HTTPResponse := TToolHTTP.Post(CST_URL_WS_GET_PEBBLE, Param);
    finally
      FreeAndNil(Param);
    end;

    if HTTPResponse.Valid then
    begin
      try
        Value := TJSONObject.ParseJSONValue(HTTPResponse.Content);
        Ar := Value.FindValue('item') as TJSONArray;

        try
          if Assigned(Ar) then
          begin
            try
              i := 0;

              while (i <= Ar.Count - 1) and not Terminated do
              begin
                Id := Ar.Items[i].GetValue<integer>('id');

                if not FCheckDuplicate or
                   (FCheckDuplicate and not FListMarker.Exists(Id)) then
                begin
                  Latitude  := Ar.Items[i].GetValue<string>('latitude');
                  Longitude := Ar.Items[i].GetValue<string>('longitude');

                  LatitudeDouble  := TToolMath.StrToFloat(Latitude);
                  LongitudeDouble := TToolMath.StrToFloat(Longitude);

                  if (LatitudeDouble <> 0) and (LongitudeDouble <> 0) then
                  begin
                    CustomMapMarker := TCustomMapMarker.Create;
                    CustomMapMarker.Id        := Id;

                    TThread.Synchronize(nil,
                    procedure
                    var
                      Descr: TMapMarkerDescriptor;
                    begin
                      if not Terminated then
                      begin
                        Descr := TMapMarkerDescriptor.Create(TMapCoordinate.Create(LatitudeDouble, LongitudeDouble), '');
                        Descr.Snippet := CustomMapMarker.Id.ToString;
                        Descr.Icon := FImgList.Bitmap(TSizeF.Create(CST_IMG_SIZE, CST_IMG_SIZE), CST_IMG_MARKER_FACEBOOK)

                        CustomMapMarker.Marker := FMapView.AddMarker(Descr);
                        FListMarker.Add(CustomMapMarker);
                      end;
                    end);
                  end;
                end;
                i := i + 1;
              end;
            except
              on E: Exception do
                raise Exception.Create('[On loading] ' + E.Message);
            end;
          end;
        finally
          FreeAndNil(Value);

          if FShowMapViewAtEnd then
          begin
            TThread.Synchronize(nil,
            procedure
            begin
              FMapView.Visible := True;
            end);
          end;
        end;
      except
        on E: Exception do
          raise Exception.Create('[loading] ' + E.Message);
      end;
    end;
  finally
    FIsTerminate := True;
  end;
end;

我花了很多时间来查看可能导致这些错误的原因,但没有奏效。你在某处看到错误了吗?谢谢

标签: androiddelphifiremonkey

解决方案


好的,在 FPebbleThread.Terminate 之后,我会在你的 frMain.LoadMapMarker 中推送一个“FPebbleThread.WaitFor”。

比如这个

if Assigned(FPebbleThread) then
begin
  FPebbleThread.Terminate;
  FPebbleThread.WaitFor;
end;

TThread.Terminate 方法只是设置了一个布尔值,当您创建一个新线程时,您的线程肯定不会正确终止。


推荐阅读