3

新しいクラスを定義する場合、IndyコマンドTIdThreadSafeを使用してクラスMyPrivateClassをスレッドセーフにすることはできますか?

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

このクラス内のTListおよびTBitmapアイテムにアクセスするため、MyPrivateClassはスレッドセーフではありません

TCPServer.Onexecutdeコードを次のスタイルに変更した場合

    ......

     aNewIndyClass  :=  MyNewIndyClass.Create; 

     aNewIndyClass.FLocal.CallFuntionA; 

     aNewIndyClass.FLocal.CallFuntionB; 

      ......

このアプローチのアイデア:MyPrivateClassコードを変更せずに、別のクラスで実行中のIndyサーバーのリクエストを追加するだけです。

4

1 に答える 1

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;

また、MyNewIndyClassクラスのプライベートメンバーまたは保護されたメンバーにアクセスするには、プロパティ(つまり、getter / setter)を使用することをお勧めします。

ちなみに、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;
于 2012-10-28T23:12:54.277 に答える