使用 Delphi 和 Indy 10.6 我找不到 TIdServerContext 的 OnWork

With Delphi and Indy 10.6 I can't find OnWork for TIdServerContext

在设置我的 TCP Client/Server 系统时,我将 TIdServerContext 子类化以添加索引标志,但似乎没有 OnWork 事件。我需要重置一个计时器,比如说 uploading/downloading 一个大文件,很多 Indy 组件都有一个 OnWork 事件适合这个,但我找不到 TIdServerContextTIdTCPServer,根据其他帖子,TIdTCPServer.OnStatus 事件似乎未实现。

下面是我如何实现 TIdServerContext:

TUserContext = Class(TIdServerContext)
Protected
  FUserID: Integer;
Public
  Property UserID: Integer Read FUserID Write FUserID Default 0;
End;

Procedure FormCreate(Sender: TObject);
Begin
  Server.ContextClass := TUserContext;
End;

Procedure ServerExecute(AContext: TIdContext);
Var
  I: Integer;
Begin
  I := TUserContext(AContext).UserID;
  ...
End;

OnWork... 事件在 TIdComponent class 中,TIdServerContext 不是从中派生的。但是,TIdTCPConnectionTIdIOHandler 可以。 TIdContext 有一个 public Connection 属性,因此在您服务器的事件(OnConnectOnExecute 等)中,您可以将处理程序分配给TIdConnection.OnWork... 需要的事件:

procedure TMyForm.ServerConnect(AContext: TIdContext);
begin
  AContext.Connection.Tag := NativeInt(AContext);
  AContext.Connection.OnWork := WorkHandler;
end;

procedure TMyForm.WorkHandler(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
var
  Ctx: TUserContext;
begin
  Ctx := TUserContext(TIdTCPConnection(ASender).Tag);
  // use Ctx members as needed...
end;

或者,另一种不使用 TagAContext 传递给 WorkHandler 的方法:

procedure TMyForm.ServerConnect(AContext: TIdContext);
var
  Handler: TWorkEvent;
begin
  Handler := WorkHandler;
  TMethod(Handler).Data := AContext;
  AContext.Connection.OnWork := Handler;
end;

procedure TMyForm.WorkHandler(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
var
  Ctx: TUserContext;
begin
  Ctx := TUserContext(Self);
  // use Ctx members as needed...
end;

另一种处理方法是覆盖 TIdServerContext 构造函数,它接收 TIdTCPConnection 对象作为参数。你可以让你的处理程序成为 TUserContext class 本身的方法,并让它的构造函数立即分配 OnWork... 事件,而不是等待服务器的 On(Connect|OnExecute) 事件首先触发:

type
  TUserContext = Class(TIdServerContext)
  protected
    FUserID: Integer;
    procedure WorkHandler(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
  public
    constructor Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TIdContextThreadList = nil); override;
    property UserID: Integer read FUserID write FUserID;
  end;

constructor TUserContext.Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TIdContextThreadList = nil);
begin
  inherited;
  AConnection.OnWork := WorkHandler;
end;

procedure TUserContext.WorkHandler(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
  // use Self members as needed...
end;

或者,如果您只是根据需要参加活动:

type
  TUserContext = Class(TIdServerContext)
  protected
    FUserID: Integer;
    procedure WorkHandler(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
  public
    procedure StartWorkTimer;
    procedure StopWorkTimer;
    property UserID: Integer read FUserID write FUserID;
  end;

procedure TUserContext.StartWorkTimer;
begin
  Connection.OnWork := WorkHandler;
end;

procedure TUserContext.StopWorkTimer;
begin
  Connection.OnWork := nil;
end;

procedure TMyForm.ServerExecute(AContext: TIdContext);
var
  Ctx: TUserContext;
begin
  Ctx := TUserContext(AContext);

  ...

  if (some condition) then
    Ctx.StartWorkTimer;

  ...

  if (some other condition) then
    Ctx.StopWorkTimer;

  ...
end;