0

ObjectLinks と ObjectBacklinks の 2 つのプロパティ (ao) を含む Tinterfacedobject を作成したいと考えています。Objectlinks には他のオブジェクトへのインターフェース参照が含まれ、ObjectBacklinks にはこれらのリンクの逆が含まれます。

どちらのプロパティも TWeakIntfDictionary = class(TDictionary) で構成されます Backlinks プロパティは ObjectLinks.ValueNotify イベントで維持されます

元のオブジェクトが解放されたときにインターフェイス参照がディクショナリから削除されるようにするために、通知アルゴリズム (TFmxObject が使用するものと同じ) が配置されます。

疑わしいように、同じインターフェイス オブジェクトへの非常に多くの参照を作成するときに、あらゆる種類の循環参照の問題に遭遇しています :( しかし、私はこの問題から抜け出せないようです。破棄されているオブジェクトから FreeNotification が呼び出されると、すべてがうまくいきますFreeNOTification から戻るまで問題ありません。その時点で、オブジェクトの .Destroy が再度呼び出されます :-(

 {1 Dictionary of interfaces (using weak references) using Free notification }
  TWeakIntfDictionary = class(TDictionary<int64, IInterface>, IFreeNotificationMonitor)
  protected
    procedure ValueNotify(const Value: IInterface; Action: TCollectionNotification); override;
  public
    procedure FreeNotification(aObject: TObject);
  end;

  implementation

  procedure TWeakIntfDictionary.FreeNotification(aObject: TObject);
  var
    lObj: TPair<int64, IInterface>;
  begin
    //Object is going to be destroyed, remove it from dictionary
    for lObj in Self do
    begin
      if (lObj.Value as TObject).Equals(aObject) then
      begin
        Remove(lObj.Key);
        Break;
      end;
    end;
  end;

  procedure TWeakIntfDictionary.ValueNotify(const Value: IInterface; Action: TCollectionNotification);
  var
    lDestrIntf: IFreeNotificationBehavior;
  begin
      // When a TObject is added to the dictionary, it must support IDestroyNotification
      // This dictionary is than added to the notificationlist of the TObject
    if Supports(Value, IFreeNotificationBehavior, lDestrIntf) then
      case Action of
        cnAdded:      begin
                        lDestrIntf.AddFreeNotify(Self);
                        lDestrIntf._Release;
                      end;
        cnRemoved,
        cnExtracted:  begin
                        lDestrIntf.RemoveFreeNotify(Self);
                      end;
      end
    else
      raise EWeakInftDictionaryException.Create('Object added to TWeakIntfDictionary does not support IFreeNotificationBehavior');

    inherited;

  end;

WeakReferences Dictionary の既存の実装を知っている人はいますか? これを解決する方法はありますか?

4

1 に答える 1

0

次のコードで解決策を見つけました

procedure TWeakIntfDictionary.FreeNotification(aObject: TObject);
var
  ...
begin
  //Object is going to be destroyed, remove it from dictionary
  lSavedEvent := FDict.OnValueNotify;
  FDict.OnValueNotify := nil;
  lRemoveList := TList<TKey>.Create;
  try
    for lPair in FDict do
    begin
      pointer(lIntf) := lPair.Value;
      if (lIntf as TObject) = aObject then
        lRemoveList.Add(lPair.Key);
    end;
    pointer(lIntf):=nil; // avoid _release for the last item

    for lKey in lRemoveList do
      FDict.Remove(lKey);

  finally
    FDict.OnValueNotify := lSavedEvent;
    lRemoveList.Free;
  end;
end;
于 2012-10-26T08:09:57.527 に答える