在Delphi中,在事件中释放发送者是正确的方法吗?

问题描述 投票:0回答:1

所以,假设我们有一堂这样的课程:

  TFieldsReadyEvent = procedure(Sender: TObject; Code, AuthorizatedID: string) of object;
  TCatcherServer = class(TServer)
  private
    FOnFieldsReady: TFieldsReadyEvent;
    FCode: string;
    FAuthoID: string;
    FAuthorizationType: TAuthorizationType;
    function GetAuthorizationType: string;
    function GetCode: string;
    function GetEntityID: string;
  public
    property OnFieldsReady: TFieldsReadyEvent read FOnFieldsReady write FOnFieldsReady;
    property Code: string read GetCode;
    property EntityID: string read GetEntityID;
    property AuthorizationType: string read GetAuthorizationType;
    procedure Callback(Session: TIdContext; Req: TIdHTTPRequestInfo; Res: TIdHTTPResponseInfo); override;
  end;

其中

Callback
程序如下所示:

procedure TCatcherServer.Callback(Session: TIdContext;
  Req: TIdHTTPRequestInfo; Res: TIdHTTPResponseInfo);
begin
  inherited Callback(Session, Req, Res);
  if (Req.Params.Values['code'] <> '') and ((Req.Params.Values['shop_id'] <> '') or (Req.Params.Values['main_account_id'] <> '')) then
  begin
    Res.ResponseNo := 200;
    Res.ResponseText := '{"message":"continue on the application"}';
    FCode := Req.Params.Values['code'];
    if (Req.Params.Values['shop_id'] <> '') then
    begin
      FAuthorizationType := atShopAuthorization;
      FAuthoID := Req.Params.Values['shop_id'];
    end else
    begin
      FAuthorizationType := atMainAccountAuthorization;
      FAuthoID := Req.Params.Values['main_account_id'];
    end;

    FOnFieldsReady(Self, FCode, FAuthoID);
  end else
  begin
    Res.ResponseNo := 400;
    Res.ResponseText := '{"message":"Something went wrong."}';
  end;
end;

在我的表单中包含一个能够释放 TCatcherServer 实例的事件处理程序是正确的方法吗?示例如下:

{Form1 public declarations}
procedure FieldsReadyHandler(Sender: TObject; Code, AuthorizatedID: string);
procedure TForm1.Button1Click(Sender: TObject);
begin
  VarServer := TCatcherServer.Create;
  VarServer.Listen(7070);
  VarServer.OnFieldsReady := FieldsReadyHandler;
end;

procedure TForm1.FieldsReadyHandler(Sender: TObject; Code,
  AuthorizatedID: string);
begin
  ServerLog.Lines.Add(Code);
  ServerLog.Lines.Add(AuthorizatedID);
  ServerLog.Lines.Add((Sender as TCatcherServer).AuthorizationType);

  Sender.Free;
end;

TL;DR 在这种情况下使用事件释放发送者是否是正确的方法(在事件触发后,我获得了所需的数据并且不再需要发送者)。如果不是,正确的做法是什么?

delphi pascal
1个回答
0
投票

Sender
从其自己的事件中释放通常是不安全的。您不知道事件处理程序退出后还可能需要什么来访问
Sender

举个例子 - 如果所讨论的

Sender
是拥有
TIdHTTPServer
的对象,而该对象正在触发您的
Callback()
方法,那么您将尝试释放
Sender
,从而释放
TIdHTTPServer
,而
TIdHTTPServer
仍在等待
Callback()
退出。这会导致僵局。

如果必须释放

Sender
,则应异步执行此操作,以便为调用者/RTL 提供额外的时间来完成对
Sender
的使用。例如,通过使用
TThread.Queue(nil, Sender.Free);
请注意,
TIdHTTPServer
在工作线程中触发其
OnCommand...
事件,但
TThread.Queue()
在主线程中运行其谓词,因此请确保
Sender
的销毁是线程-安全。

© www.soinside.com 2019 - 2024. All rights reserved.