2

AsyncCallsをDelphi7プロジェクトの1つに統合しようとしましたが、クラスのパラメーターなしのプロシージャをまだ呼び出すことができませんでした。

私がやりたいこと:

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

var
  TestCall: IAsyncCall;

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

これは不可能であり、エラーE2036変数が必要になります(このエラーメッセージは、式または定数のアドレスを取得しようとしたときに発生します)。

私のWaitForItプロシージャにこののプロシージャのようなパラメータがある場合はいつでも可能です。
さらに、それは可能ですがLocalAsyncCall、私は常にローカルプロシージャを宣言したいとは限りません。

また、静的にすると(つまりprocedure TestCalculation、ではなくprocedure TMyForm.TesCalculation)、このプロシージャを呼び出すこともできます。その後、正常に呼び出すことができますがRunTestCall := AsyncCall(@TestCalculation, []);、これはに属するプロシージャでは機能しませんTMyForm

質問

TestCalculationクラス内の別のプロシージャからAsyncCallsを使用して、例()のパラメータなしのクラスプロシージャを呼び出すにはどうすればよいですか?

4

1 に答える 1

4

AsyncCall1 つのパラメータを受け取るプロシージャを渡すことを想定しています。パラメータを渡したくない場合は、パラメータを追加して無視してください。

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プロシージャはそれをレジスタから読み取りません。

于 2012-12-13T13:53:23.647 に答える