2014-01-28 41 views
2

創建線程對象時,我想從需要同步的應用程序調用代碼。問題是我不知道如何使用參數調用Synchronize來應用函數。將參數傳遞給同步過程調用

說我們有

procedure ThreadObject.Execute; 
var 
    val1,val2:integer; 
    Star:string; 
begin 
    Synchronize(funcyfunc); //how to pass val1,val2,star here? 
end; 

其中funcyfunc被定義爲跟隨

procedure OtherClass.funcyfunc(param1,param2:integer;spok:string); 
begin 
    letsCallFriends(spok,param1); 
    letsCallFriends(spok,param2); 
end; 

現在奇的解決方案,這將是在ThreadObject私下裏說

,並在我們的實施

procedure ThreadObject.starVal; 
begin 
    funcyfunc(Star,val1,val2); 
end; 

,並在線程中執行,我們改變

procedure ThreadObject.Execute; 
var 
    val1,val2:integer; 
    Star:string; 
begin 
    Synchronize(starVal); //how to pass val1,val2,star here? 
end; 

但這是一件麻煩事,因爲每個過程調用必須有一個全局變量。有沒有更好的辦法?

代碼:

unit ThreadObject; 

interface 

uses 
    Classes; 

type 
    TThreadObject= class(TThread) 
    private 
    star:string; 
    val1,val2:integer; 
    procedure starVal; 
    protected 
    procedure Execute; override; 

    //assume we have a constructor that ini the star val1 val2. 
    end; 

implementation 

{ TThreadObject } 

procedure ThreadObject.Execute; 
var 
    val1,val2:integer; 
    Star:string; 
begin 
    Synchronize(starVal); //how to pass val1,val2,star here? 
end; 

procedure ThreadObject.starVal; 
begin 
    funcyfunc(Star,val1,val2); 
end; 

end. 
+2

['This way way](http://pastebin.com/WD2LYNE5)。 – TLama

+3

有一個很好的博客文章處理這個http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/ –

+0

可能重複的[傳遞值同步線程]( http://stackoverflow.com/questions/16870387/passing-value-to-synchronize-thread) – CinCout

回答

7

使用匿名方法

正如你可以在手冊中爲TThread.Synchronize

Synchronize(
    procedure 
    begin 
    Form1.Memo1.Lines.Add('Begin Execution'); 
    end); 

讀取。在引用的變量Form1將種等來複制並保存直到該過程被執行的上面的例子(被稱爲可變捕獲)。

注:大衛反對「複製變量」的想法,他可能是正確的。然而,討論所有的角落案例和實施細節將是一個矯枉過正的問題。他與「全局變量」OTOH的比較可能會遇到遞歸程序等問題。所有簡單易懂的類比都非常粗糙,並且以某種方式傾斜了ISTM。

您的匿名程序應該使用的變量val1val2然後他們應該得到捕獲太

http://docwiki.embarcadero.com/Libraries/XE5/en/System.Classes.TThread.Synchronize

+3

FWIW,該變量不**複製**。它被**捕獲**。如果你有另一個捕捉同一個變量的anon方法,那麼兩個anon方法都會引用** same **變量。另一種匿名方法可以看到通過一個匿名方法對該var所做的更改。這樣一個捕獲的變量從本地變爲全局。 –

+0

@DavidHeffernan,如果本地過程本身更改創建兩個匿名方法之間的值? –

+3

所有三方,即聲明本地人的程序,以及兩個匿名方法,都指向相同的變量。事實上,變量不再駐留在堆棧上,因爲anon方法的範圍當然可以超過聲明變量的過程的範圍。捕獲的變量被提升到駐留在堆上的對象中。 –

2

如果您使用德爾福的舊版本不支持匿名方法,你在你的課堂上製作你的「參數」字段。即

procedure ThreadObject.Execute; 
var 
    val1,val2:integer; 
    Star:string; 
begin 
    FVal1 := val1; 
    FVal2 := val2; 
    FStar := Star; 
    Synchronize(funcyfunc); 
end; 

procedure ThreadObject.FuncyFunc; 
begin 
    //Do stuff with FVal1, FVal2 and FStar 
end; 

注意這些全球。
這也是相當安全的,因爲Synchronize的目的是確保兩個線程相互協調。因此,假設您沒有其他線程試圖訪問相同的數據,您將不會有任何競爭條件。

是的,它有點「klunky」,但這是在較新版本的Delphi中使用匿名方法的優勢。