0

dbテーブルをパラメーターとして受け取るスレッドを取得しましたが、同時にそのdbテーブルに書き込めないという問題が発生しました。

TMyThreadの1つのインスタンスは「Member」のdbテーブルを持つことができ、別のインスタンスは「Staff」を持つことができますが、同じテーブルで2つのスレッドが開いている場合があります。

したがって、コードをクリティカルセクション(または同様のセクション)でラップする必要がありますが、(fMemberTable、fStaffTable)のようないくつかのクリティカルセクションのような汚いものは必要ありません...

begin
    if fDBTable = 'Member' then
        fMemberTable.Enter
    else if fDbTable = 'Staff' then
    ....

面倒になるように8つのテーブルがあります

TCricalSection(fMemberTable).Enter; または、「スケーリング」して使用するのが簡単なこれを行うための何らかの方法はありますか?

他のテーブルを抑制したくないので、関数に関する1つのクリティカルセクションは意味がありません。

4

2 に答える 2

2

できるよ:

TMonitor.Enter(fMemberTable);
try
  // Do your stuff
finally TMonitor.Exit(fMemberTable);
end;

これはスピン ロックであり、真のクリティカル セクションではないことに注意してください。多くの衝突が発生しない場合は非常に実用的ですが、スレッドが定期的に相互にブロックする場合は、クリティカル セクションにフォールバックすることをお勧めします。スピンロックは、定義上、ビジーウェイトロックです。

しかし、これを導入した Delphi のバージョンがわからず、バージョン固有のタグがありません。

于 2011-04-14T09:13:59.373 に答える
0

この単元で定義された My class などのクリティカル セクション リストを使用できます。

interface
uses Classes, SyncObjs;

type
  { TCriticalSectionList by jachguate }
  { http://jachguate.wordpress.com }
  TCriticalSectionList = class
  private
    FCSList: TThreadList;
    FNameList: TStringList;
    function GetByName(AName: string): TCriticalSection;
  public
    constructor Create();
    destructor Destroy(); override;
    property ByName[AName: string]: TCriticalSection read GetByName; default;
  end;

  function CSList: TCriticalSectionList;

implementation
uses SysUtils;

{ TCriticalSectionList }

constructor TCriticalSectionList.Create;
begin
  inherited;
  FCSList := TThreadList.Create;
  FNameList := TStringList.Create;
end;

destructor TCriticalSectionList.Destroy;
var
  I: Integer;
  AList: TList;
begin
  AList := FCSList.LockList;
  for I := AList.Count - 1 downto 0 do
    TCriticalSection(AList[I]).Free;
  FCSList.Free;
  FNameList.Free;
  inherited;
end;


function TCriticalSectionList.GetByName(AName: string): TCriticalSection;
var
  AList: TList;
  AIdx: Integer;
begin
  AList := FCSList.LockList;
  try
    AName := UpperCase(AName);
    AIdx := FNameList.IndexOf(AName);
    if AIdx < 0 then
    begin
      FNameList.Add(AName);
      Result := TCriticalSection.Create;
      AList.Add(Result);
    end
    else
      Result := AList[AIdx];
  finally
    FCSList.UnlockList;
  end;
end;

var
  _CSList: TCriticalSectionList;

function CSList: TCriticalSectionList;
begin
  if not Assigned(_CSList) then
    _CSList := TCriticalSectionList.Create;
  Result := _CSList;
end;

initialization
  _CSList := nil;
finalization
  _CSList.Free;
end.

このクラスは基本的に、「名前」でアクセスできるクリティカル セクションのリストを定義します。特定の名前のクリティカル セクションを初めて要求すると、そのクリティカル セクションが自動的に作成されます。提供されている CSList 関数を使用して、このクラスの 1 つのインスタンスにアクセスする必要があります。

リストのインスタンスが破棄されると、すべてのクリティカル セクションが破棄されます。たとえば、アプリケーションの終了時に「デフォルト」インスタンスが破棄されます。

次の例のようなコードを記述できます。

begin
  CSList[fDBTable].Enter;
  try
    DoStuff;
  finally
    CSList[fDBTable].Leave;
  end;
end;

楽しみ。

于 2011-04-14T23:34:26.190 に答える