2013-10-31 2 views
10

주 스레드와 백그라운드 스레드간에 사용할 수있는 "threadsafe"일반 속성을 만들었습니다. 모든 속성과 변수에 대해 Lock-Objects를 만드는 데 지겨워서 만들었습니다.일반 Threadsafe 속성

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; 

답변

15

코드가 올바르므로 속성에 대한 읽기/쓰기 권한을 직렬화합니다. 유일한 주석은 별도의 잠금 객체를 만들 필요가 없다는 것입니다. PropLock을 삭제하고 Self을 잠글 수 있습니다.

코드베이스에 거의 동일한 클래스가 있습니다. 유일한 차이점은 다음과 같습니다 아직도 TMonitor을 신뢰하지 않기 때문에

  1. 나는 TMonitor보다는 중요 섹션을 사용합니다. 초기 버전에는 많은 버그가 있었으며 이것이 내 자신감을 손상 시켰습니다. 그러나, 나는 지금 TMonitor 코드가 가장 정확하다고 의심합니다. 그래서 당신이 변할 이유가 없습니다.
  2. 나는 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; 

나는이 클래스를 작성하는 정말 하나의 방법이 생각!

+1

당신의 대답은 Thnx이고, 나는 당신이 수업의 버전을 공유했다는 사실에 정말로 감사드립니다. 나는이 솔루션을 스스로 만들 수있는 프로그래머로서 더 자신감을 느낀다. 내 벨트 아래에만 델파이의 1 년;). –

+0

버퍼를 보유하는 클래스가 CPU 캐시 라인보다 작은 경우 중요한 섹션에 성능 문제가있을 수 있습니다. https://www.delphitools.info/2011/11/30/fixing-tcriticalsection/를 참조하십시오. 클래스 정의에 작은 정렬 버퍼를 추가하고 TCriticalSection 클래스 대신 OS 중요 섹션에 의존하는 것이 더 안전 할 수도 있습니다 . –