Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi-有没有与C#lock等价的东西?_C#_Delphi_Multithreading_Delphi 6 - Fatal编程技术网

Delphi-有没有与C#lock等价的东西?

Delphi-有没有与C#lock等价的东西?,c#,delphi,multithreading,delphi-6,C#,Delphi,Multithreading,Delphi 6,我正在用Delphi编写一个多线程应用程序,需要使用一些东西来保护共享资源 在C#中,我会使用“lock”关键字: 在Delphi中我找不到任何类似的方法,我只找到了TThread.Synchronize(someMethod)方法,它通过在主VCL线程中调用someMethod来防止潜在的冲突,但这并不是我想要做的 编辑:我使用的是Delphi 6(Un),幸运的是,您不能在Delphi 6中锁定任意对象(尽管您可以在更新的版本,2009和更高版本中锁定),因此您需要有一个单独的锁定对象,通常

我正在用Delphi编写一个多线程应用程序,需要使用一些东西来保护共享资源

在C#中,我会使用“lock”关键字:

在Delphi中我找不到任何类似的方法,我只找到了TThread.Synchronize(someMethod)方法,它通过在主VCL线程中调用someMethod来防止潜在的冲突,但这并不是我想要做的

编辑:我使用的是Delphi 6(Un),幸运的是,您不能在Delphi 6中锁定任意对象(尽管您可以在更新的版本,2009和更高版本中锁定),因此您需要有一个单独的锁定对象,通常是一个关键部分

(注意:文档来自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;

如上所述,对于不在本地范围外调用且不获取任何其他锁的短代码,您可以通过
SyncObjs.TCriticalSection

使用关键部分 对于更长/更复杂的代码,您可以使用
SyncObjs.TMutex
,它是可等待的(带有超时),如果所属线程死亡,它不会暂停,并且可以通过名称与其他进程共享。
使用这些包装器可以更轻松地更改同步层


在任何情况下,都要小心这里的龙:

虽然不像c#那么简单,但下面的内容可能适合您。

  with Lock(mySharedObj) do
  begin
    //...do something with mySharedObj
    UnLock;
  end;
简而言之

  • 为您希望保护的每个实例保留一个列表
  • 当第二个线程调用
    锁(mySharedObj)
    时,将在内部列表中搜索现有锁。如果未找到现有锁,将创建新锁。如果另一个线程仍具有锁,则新线程将被阻塞
  • Unlock
    是必需的,因为我们无法确定在调用
    Lock
    的方法的末尾,对ILock实例的引用是否会超出范围。(如果可以,可以删除
    解锁
请注意,在这种设计中会为每个要保护的对象实例创建一个TLock,在应用程序终止之前不会释放它。
这是可以考虑的,但它会涉及到混乱与_AddRef&_发布



Delphi 6中没有等效项。从Delphi2009开始,您可以使用这些方法获取任意对象上的锁

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

(您需要“系统”前缀,因为TMonitor名称与表单单元中的类型冲突。另一种选择是使用全局和函数。)

使用类帮助程序,您可以使用此选项。但不能与旧版本一起使用。但我建议仅在XE5中使用TMonitor。因为它比TRTLCriticalSection慢很多


至少您可以调用windows API关键部分锁列表还需要以某种方式排序,并通过二进制搜索完成“定位”,以提高性能。@Ken Bourassa:是的,还有很多改进的余地。不过,我们的目的只是展示如何使用Delphi 6实现c#中使用的类似构造。Delphi 2009引入了锁定任何对象的功能-请参见“为什么在Delphi 2009中TObject的大小翻了一番?”是的,我后来了解到了这一点,但是这个问题已经被编辑成了Delphi6,所以我没有费心更新我的答案,只是为了把它放回头版。不过我应该留下评论。但是,我要指出,我反对那篇文章中的观点。锁定任何对象的能力都不是一件好事,如果不知道自己在做什么,很容易导致死锁。因为任何人都可以锁定任何对象,所以有时他们会锁定。最好专门分配锁定对象并使用它们。(在这方面)毫无意外
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.
System.TMonitor.Enter(obj);
try
  // ...
finally
  System.TMonitor.Exit(obj);
end;
THelper = class helper for TObject
  procedure Lock;
  procedure Unlock;
end;

procedure THelper.Lock;
begin
  System.TMonitor.Enter(TObject(Self));
end;

procedure THelper.Unlock;
begin
  System.TMonitor.Exit(TObject(Self));
end;