我创建了这个“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;
我想真的只有一种方法来写这个课程!