Delphi - есть ли какой-нибудь эквивалент C # блокировки?

<form action="product.php" method="post" name="frmProduct" id="frmProduct" enctype="multipart/form-data">

<input id="submit_value" type="button" name="submit_value" value="">

</form>

<script type="text/javascript">

document.getElementById("submit_value").onclick = submitAction;

function submitAction()
{
    document.getElementById("frmProduct").submit();
    return false;
}
</script>

EDIT: я случайно поменял идентификатор вокруг

13
задан Ondra C. 1 July 2010 в 19:53
поделиться

4 ответа

(Не), к счастью, вы не можете заблокировать произвольные объекты в Delphi 6 (хотя вы можете это сделать в более поздних версиях, 2009 и более поздних), поэтому вам нужен отдельный объект блокировки, обычно критический раздел.

TCriticalSection (примечание: документация из FreePascal, но она существует и в Delphi):

Пример кода:

type
  TSomeClass = class
  private
    FLock : TCriticalSection;
  public
    constructor Create();
    destructor Destroy; override;

    procedure SomeMethod;
  end;

constructor TSomeClass.Create;
begin
  FLock := TCriticalSection.Create;
end;

destructor TSomeClass.Destroy;
begin
  FreeAndNil(FLock);
end;

procedure TSomeClass.SomeMethod;
begin
  FLock.Acquire;
  try
    //...do something with mySharedObj
  finally
    FLock.Release;
  end;
end;
17
ответ дан 1 December 2019 в 20:11
поделиться

Хотя это не так просто, как C #, следующее может сработать для вас.

  with Lock(mySharedObj) do
  begin
    //...do something with mySharedObj
    UnLock;
  end;

Вкратце

  • список ведется для каждого экземпляра , который вы хотите защитить.
  • , когда второй поток вызывает блокировку (mySharedObj) , во внутреннем списке выполняется поиск существующей блокировки. Если существующая блокировка не найдена, будет создана новая блокировка. Новый поток будет заблокирован, если другой поток все еще имеет блокировку.
  • Разблокировка необходима, потому что мы не можем быть уверены, что ссылка только на экземпляр ILock выйдет из области в конце метода, вызывающего Lock . (Если бы мы могли, разблокировку можно было бы удалить).

Обратите внимание, что в этом проекте один TLock создается для каждого экземпляра объекта, который вы хотите защитить, без его освобождения до завершения работы приложения.
Это можно было бы учесть, но это потребовало бы возиться с _AddRef & _Release.


unit uLock;

interface

type
  ILock = interface
    ['{55C05EA7-D22E-49CF-A337-9F989006D630}']
    procedure UnLock;
  end;

function Lock(const ASharedObj: TObject): ILock;

implementation

uses
  syncobjs, classes;

type
  _ILock = interface
    ['{BAC7CDD2-0660-4375-B673-ECFA2BA0B888}']
    function SharedObj: TObject;
    procedure Lock;
  end;

  TLock = class(TInterfacedObject, ILock, _ILock)
  private
    FCriticalSection: TCriticalSection;
    FSharedObj: TObject;
    function SharedObj: TObject;
  public
    constructor Create(const ASharedObj: TObject);
    destructor Destroy; override;
    procedure Lock;
    procedure UnLock;
  end;

var
  Locks: IInterfaceList;
  InternalLock: TCriticalSection;

function Lock(const ASharedObj: TObject): ILock;
var
  I: Integer;
begin
  InternalLock.Acquire;
  try
    //***** Does a lock exists for given Shared object
    for I := 0 to Pred(Locks.Count) do
      if (Locks[I] as _ILock).SharedObj = ASharedObj then
      begin
        Result := ILock(Locks[I]);
        Break;
      end;

    //***** Create and add a new lock for the shared object
    if not Assigned(Result) then
    begin
      Result := TLock.Create(ASharedObj);
      Locks.Add(Result);
    end;
  finally
    InternalLock.Release;
  end;
  (Result as _ILock).Lock;
end;

{ TLock }

constructor TLock.Create(const ASharedObj: TObject);
begin
  inherited Create;
  FSharedObj := ASharedObj;
  FCriticalSection := TCriticalSection.Create;
end;

destructor TLock.Destroy;
begin
  FCriticalSection.Free;
  inherited Destroy;
end;

procedure TLock.Lock;
begin
  FCriticalSection.Acquire;
end;

function TLock.SharedObj: TObject;
begin
  Result := FSharedObj;
end;

procedure TLock.UnLock;
begin
  FCriticalSection.Release;
end;

initialization
  Locks := TInterfaceList.Create;
  InternalLock := TCriticalSection.Create;

finalization
  InternalLock.Free;
  Locks := nil

end.
3
ответ дан 1 December 2019 в 20:11
поделиться

Как сказано, для короткого кода, который не вызывает вне локальной области и не требует каких-либо других блокировок, вы можете использовать критические секции через SyncObjs.TCriticalSection ,
для более длинного / более сложного кода вы можете использовать SyncObjs.TMutex , который является ожидаемым (с тайм-аутом), не останавливается, если поток-владелец умирает, и может использоваться по имени с другими процессами.
Использование этих оболочек упрощает внесение изменений в уровень синхронизации.

Во всех случаях остерегайтесь драконов: мой ответ на Разница между функцией WaitFor для TMutex delphi и ее эквивалентом в Win32 API

0
ответ дан 1 December 2019 в 20:11
поделиться

В Delphi 6 нет эквивалента. Начиная с Delphi 2009, вы можете использовать методы System.TMonitor для захвата блокировок произвольных объектов.

System.TMonitor.Enter(obj);
try
  // ...
finally
  System.TMonitor.Exit(obj);
end;

(Префикс "System" нужен потому, что имя TMonitor конфликтует с типом в блоке Forms. Альтернативой является использование глобальных функций MonitorEnter и MonitorExit )

.
11
ответ дан 1 December 2019 в 20:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: