如果我定义一个新的类
,我可以使用Indy Command TIdThreadSafe来创建MyPrivateClass类安全吗? MyNewIndyClass = Class(TIdThreadSafe)
FLocal : MyPrivateClass
create
......
end;
我的MyPrivateClass不是Threadsafe,因为我访问此类中的TList和TBitmap项目
如果我将TCPServer.Onexecutde代码更改为以下样式
......
aNewIndyClass := MyNewIndyClass.Create;
aNewIndyClass.FLocal.CallFuntionA;
aNewIndyClass.FLocal.CallFuntionB;
......
这种方法的想法:保持MyPrivateClass代码不变,只需在单独的类中添加Indy Server onexecute的请求
答案 0 :(得分: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及更新版本,您可以获得Generics的优势。通用线程安全类的简短示例实现可以是:
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;