2012-12-13 20 views
2

試圖AsyncCalls融入我的德爾福7個項目中的一個,我還沒有能夠調用類的參數的過程。如何使用AsyncCalls調用無參數類過程?

我想要做什麼:

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的程序不起作用。

問題

如何與AsyncCalls打電話在我的例子(TestCalculation)的參類程序從另一個過程我的類中?

+0

asynccalls是否支持匿名方法,如OTL?所以你可以把這個呼叫轉換成臨時程序?像'AsyncCall(procedure(param:integer)begin TMyClass.MyMethod(); end)'?或者也許你可以使用OmniThreadsLibrary?對於我記得你可以只是'Parallel.Async(ProcedureName())',但你可以檢查它。至少OTL不會停止:-) –

+0

不幸的是OTL不支持Delphi 7. –

+0

運氣不好。 OTL v.1.x?儘管1.x不支持:-)但是,真的,你最好標記你的Delphi版本,這是TAGS的目的之後 –

回答

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時,你的過程不會從寄存器中讀取它。

+0

我認爲這是一種解決方法,但它看起來非常難看,並且感覺不對。 –

+1

請稍等,我會告訴你如何避免醜陋 –

+0

我會親自從這個代碼中使用的名稱中刪除'Parameterless'。如果程序是例如通過對象參數,它被定義爲'TAsyncCallArgObjectProc',所以它是指定參數的'ArgObject'。我只是把它保留爲'TAsyncCallProc'。 [+1] – TLama

相關問題