2012-10-28 41 views
3

可我用的是印地命令TIdThreadSafe使一個類MyPrivateClass線程安全的,如果我定義一個新的類如何使用TIdThreadSafe類從Indy10

MyNewIndyClass = Class(TIdThreadSafe) 
     FLocal : MyPrivateClass 
     create 
      ...... 
      end; 

我MyPrivateClass不是線程安全的,因爲我進入這裏面從TList和TBitmap項目類

如果我改變TCPServer.Onexecutde代碼對下列風格

...... 

    aNewIndyClass := MyNewIndyClass.Create; 

    aNewIndyClass.FLocal.CallFuntionA; 

    aNewIndyClass.FLocal.CallFuntionB; 

     ...... 

理念的這種做法:保持MyPrivateClass代碼不變,只需在獨立的類中添加對Indy服務器的請求1xecute

回答

3

您應該使用TIdThreadSafe類的Lock()和Unlock()方法。例如,在TCPServer.OnExecute()調用aNewIndyClass的方法是這樣的:

aNewIndyClass := MyNewIndyClass.Create; 

    aNewIndyClass.Lock; // This will enter TIdThreadSafe internal's Critical Section object 
    try 
    with aNewIndyClass do // The code between try/finally will be "atomic" 
    begin     // i.e. no other thread will be able to do anything with your object 
     ... 
     FLocal.CallFuntionA; 
     FLocal.CallFuntionB; 
     ... 
    end; 
    finally     // The use of TRY/FINALLY is MANDATORY when working with critical sections! 
    aNewIndyClass.Unlock; // This will leave the CS 
    end; 

而且最好是使用性能(即的getter/setter)訪問您MyNewIndyClass類的私有或受保護的成員。

順便說一下,如果你使用Delphi 2009和更新,你可以得到仿製藥的優勢。通用線程安全類的簡單例子實現可能是:

tThreadSafeObject<T: class> = class 
    private 
     fObject: T; 
     fCriticalSection: tCriticalSection; 
    public 
     constructor Create(cpObject: T); // We expect previously created object here. We own it! 
             // TODO: Implement ownership option? 
     destructor Destroy; 
     function Lock: T; 
     procedure Unlock; 
    end; 

{ tThreadSafe<T> } 

constructor tThreadSafeObject<T>.Create(cpObject: T); 
begin 
    inherited Create; 
    fObject := cpObject; 
    fCriticalSection := TCriticalSection.Create; 
end; 

destructor tThreadSafeObject<T>.Destroy; 
begin 
    FreeAndNil(fObject); // In this sample implementation fObject is owned so we free it 
    FreeAndNil(fCriticalSection); 
    inherited Destroy; 
end; 

function tThreadSafeObject<T>.Lock: T; 
begin 
    fCriticalSection.Enter; 
    result := fObject; 
end; 

procedure tThreadSafeObject<T>.Unlock; 
begin 
    fCriticalSection.Leave; 
end; 

用法:

procedure foo; 
var 
    tsObj: tThreadSafeObject<tMyClass>; 
begin 
tsObj := tThreadSafeObject<tMyClass>.Create(tMyClass.Create); 
try  // In real World tsObj would be variable, accessed by different threads 
    with tsObj.Lock do 
    try 
    // Do some atomic stuff here 
    finally 
    tsObj.Unlock; 
    end; 
finally 
    freeAndNil(tsObj); 
end 
end; 
+0

+1的通用解決方案 – jpfollenius

+0

解決方案已經工作在我的電腦上,現在做更多的測試 – user1769184

+0

@ user1769184,如果您發現這個有用並回答您的問題,請不要忘記接受它作爲答案 –