如何使用AsyncCalls调用无参数类过程?

时间:2012-12-13 13:42:53

标签: multithreading delphi delphi-7

尝试将AsyncCalls集成到我的一个Delphi 7项目中,我还没有能够调用类的无参数过程。

我想做什么:

TMyForm = class(TForm)
private
    procedure TestCalculation;
    procedure RunTest;
end;

var
  TestCall: IAsyncCall;

procedure TMyForm.RunTest;
begin
  TestCall := AsyncCall(TestCalculation);
end;

这是不可能的,导致错误E2036需要变量(当您尝试获取表达式的地址或常量时会出现此错误消息。)。

只要我的程序具有此example中的WaitForIt程序等参数,就可以 此外,LocalAsyncCall可能有用,但我并不总是想要声明本地程序。

如果我将其设为静态(即procedure TestCalculation而不是procedure TMyForm.TesCalculation),也可以调用此过程。然后我可以成功调用RunTestCall := AsyncCall(@TestCalculation, []);但这不适用于属于TMyForm的过程。

问题

如何在我的示例(TestCalculation)中使用AsyncCalls从我的类中的另一个过程调用无参数类过程?

1 个答案:

答案 0 :(得分:4)

AsyncCall期望您传递一个接收一个参数的过程。如果您不想传递参数,只需添加一个并忽略它。

procedure TestCalculation(IgnoreMe: Integer);
....
TestCall := AsyncCall(TestCalculation, 0);

您可以编写适配器以使调用者的代码更清晰:

type
  TAsyncCallParameterlessProc = procedure of object;

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall; overload;

......

type
  TAsyncCallParameterlessProcAdapter = class
  private
    FProc: TAsyncCallParameterlessProc;
  public
    constructor Create(Proc: TAsyncCallParameterlessProc);
    procedure IntegerProc(IgnoreMe: Integer);
  end;

{ TAsyncCallParameterlessProcAdapter }

constructor TAsyncCallParameterlessProcAdapter.Create(
  Proc: TAsyncCallParameterlessProc);
begin
  inherited Create;
  FProc := Proc;
end;

procedure TAsyncCallParameterlessProcAdapter.IntegerProc(IgnoreMe: Integer);
begin
  try
    FProc;
  finally
    Free;
  end;
end;

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall;
var
  Adapter: TAsyncCallParameterlessProcAdapter;
begin
  Adapter := TAsyncCallParameterlessProcAdapter.Create(Proc);
  Result := AsyncCall(Adapter.IntegerProc, 0);
end;

使用该适配器后,问题中的代码将编译并运行。

由于AsyncCalls已停止使用,并且不会再次修改,因此您可以轻松修改该代码以支持您所需的用法。

就个人而言,我会修改AsyncCalls并添加另一个TInternalAsyncCall子类来完成工作。

作为一个非常肮脏的黑客,这将起作用:

type
  TAsyncCallParameterlessProc = procedure of object;

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall; overload;

.....

function AsyncCall(Proc: TAsyncCallParameterlessProc): IAsyncCall;
begin
  Result := AsyncCall(TAsyncCallArgIntegerEvent(Proc), 0);
end;

这依赖于整数参数TAsyncCallArgIntegerEvent在易失性寄存器中传递的事实。因此,当框架通过0时,您的程序不会从寄存器中读取它。