我创建了这个“threadsafe”通用属性,我可以在主线程和后台线程之间使用.我做到这一点,因为我厌倦了为所有的属性和变量创建Lock对象.
TLockedProp<MyType> = class private FMyProp:MyType; PropLock:TObject; procedure SetMyProp(const Value: MyType); function GetMyProp: MyType; published property Value:MyType read GetMyProp write SetMyProp; public Constructor Create; Destructor Destroy;override; end; { TLockedProp<MyType> } constructor TLockedProp<MyType>.Create; begin inherited; PropLock:=TObject.create end; destructor TLockedProp<MyType>.Destroy; begin PropLock.Free; inherited; end; function TLockedProp<MyType>.GetMyProp: MyType; begin TMonitor.Enter(PropLock); result := FMyProp; TMonitor.Exit(PropLock); end; procedure TLockedProp<MyType>.SetMyProp(const Value: MyType); begin TMonitor.Enter(PropLock); FMyProp := Value; TMonitor.Exit(PropLock); end;
有什么问题我俯瞰吗?
这是使用这个属性类的一些代码.告诉我你的想法.
TBgThread=class(TThread) private FPaused: TLockedProp<boolean>; FCount:TLockedProp<integer>; procedure ChangeCount(pPlusMin:integer); function GetPaused:boolean; function GetCount:integer; public constructor Create; destructor Destroy;override; {Toggle Pause} procedure PausePlay; protected procedure Execute;override; published Property Paused:boolean read GetPaused; Property Count:integer read GetCount; end; constructor TBgThread.Create(); begin inherited Create(true);; FPaused:=TLockedProp<boolean>.create; FPaused.Value:=false; FCount:=TLockedProp<integer>.create; FCount.Value:=0; end; destructor TBgThread.Destroy; begin FPaused.Free; FCount.free; inherited; end; procedure TBgThread.Execute; begin inherited; Repeat if not Paused then begin Try //do something finally ChangeCount(+1); end; end else Sleep(90); Until Terminated; end; function TBgThread.GetCount: integer; begin Result:=FCount.Value; end; procedure TBgThread.ChangeCount(pPlusMin: integer); begin FCount.Value:=FCount.Value+pPlusMin; end; function TBgThread.GetPaused: boolean; begin result := FPaused.Value; end; procedure TBgThread.PausePlay; begin FPaused.Value:=not FPaused.Value; end;
解决方法
你的代码很好,并且将序列化对该属性的读/写访问.我唯一的注释是,您不需要创建一个单独的锁定对象.您可以删除PropLock并锁定Self.
我的代码库中有几乎相同的类.唯一的区别是:
>我使用关键部分而不是TMonitor,因为我仍然不信任TMonitor.早期的版本有一些错误,并且暗示了我的信心.不过,我怀疑现在TMonitor代码很可能是正确的.所以我看不到你改变的理由.
>我使用try / finally与锁定和解锁的代码.这可能对我来说有点悲观,因为很难看到你如何从getter和setter方法中的异常中有效地恢复.假设我的习惯.
FWIW,我的班级看起来像这样:
type TThreadsafe<T> = class private FLock: TCriticalSection; FValue: T; function GetValue: T; procedure SetValue(const NewValue: T); public constructor Create; destructor Destroy; override; property Value: T read GetValue write SetValue; end; { TThreadsafe<T> } constructor TThreadsafe<T>.Create; begin inherited; FLock := TCriticalSection.Create; end; destructor TThreadsafe<T>.Destroy; begin FLock.Free; inherited; end; function TThreadsafe<T>.GetValue: T; begin FLock.Acquire; Try Result := FValue; Finally FLock.Release; End; end; procedure TThreadsafe<T>.SetValue(const NewValue: T); begin FLock.Acquire; Try FValue := NewValue; Finally FLock.Release; End; end;
我想真的只有一种方法来写这个课程!