所以,假设我们有一个这样的类:
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;
Run Code Online (Sandbox Code Playgroud)
程序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;
Run Code Online (Sandbox Code Playgroud)
在我的表单中有一个能够释放 TCatcherServer 实例的事件处理程序是正确的方法吗?示例如下:
{Form1 public declarations}
procedure FieldsReadyHandler(Sender: TObject; Code, AuthorizatedID: string);
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
TL;DR在这种情况下使用事件释放发送者是正确的方法吗(触发事件后我得到了我需要的数据并且不再需要发送者)。如果不是,那么正确的做法是什么?
Sender将其从其自身事件中释放出来通常是不安全的。您不知道Sender事件处理程序退出后还可能需要访问哪些内容。
举个例子 - 如果所讨论的对象是拥有正在触发您的方法的Sender对象,那么您将尝试释放,从而释放,同时仍在等待退出。由于是一个多线程组件,在工作线程中触发其事件,因此销毁其自己的事件将导致死锁。TIdHTTPServerCallback()SenderTIdHTTPServerTIdHTTPServerCallback()TIdHTTPServerOnCommand...TIdHTTPServer
如果必须释放Sender,则应该异步执行此操作,以便为调用者/RTL 提供额外的时间来完成使用Sender。例如,通过使用TThread.Queue(nil, Sender.Free);(只需注意TThread.Queue()在主线程中运行其谓词,因此请确保Sender在此示例中您的销毁是线程安全的)。
| 归档时间: |
|
| 查看次数: |
148 次 |
| 最近记录: |