私はイベントアグリゲータに手をかけています。私は実際のアクションメソッドを格納するラッパークラスにアクションを格納しています。Delegate
、アクションメソッドのクラスWeakReference
となっています。WeakReference to Actionターゲットは常に匿名のアクションのために生きています
イベントハンドラを呼び出すときは、最初にWeakReference.IsAliveがtrueであるかどうかをチェックします。そうでなければ、それを呼び出すか、そうでなければコレクションから削除します。これは、それが所属するオブジェクトがNULL /ガベージコレクションされていることを意味するからです。
ただし、匿名のアクションを作成してイベントアグリゲータに追加すると、親クラスをnullにして(ガベージコレクタを強制的に実行しても)常にアクティブになります。
匿名メソッドでIsAliveをFALSEに設定するにはどうすればよいですか? GC.Collect()
と呼ばれ、私は新しいイベントを送信した後
void AddHandler<TEvent>(Action<TEvent> callback) {
InternalHandler handler = new InternalHandler(callback);
// Store the handler somewhere to use the callback later, if it still alive
}
class InternalHandler {
WeakReference _reference;
Delegate _method;
public InternalHandler(Delegate handler) {
_reference = new WeakReference(handler.Target);
Type messageType = handler.Method.GetParameters()[0].ParameterType;
Type delegateType = typeof(Action<,>).MakeGenericType(handler.Target.GetType(), messageType);
_method = Delegate.CreateDelegate(delegateType, handler.Method);
}
bool IsAlive => _reference != null && _reference.IsAlive;
bool Invoke(object data) {
if (!IsAlive) return false;
if (_reference.Target != null) _method.DynamicInvoke(_reference.Target, data);
return true;
}
}
とテストアプリケーション
TempObject t = new TempObject();
// Some time later
t = null;
GC.Collect();
class TempObject {
public TempObject() {
myHandler.AddHandler<SomeObject>(o => {
// Some code with a breakpoint
});
}
}
で、t
で匿名メソッドにブレークポイントをまだ呼ばれています!
WeakReference
を匿名メソッドにするにはどうすればよいですか?
詳細な返答ありがとうございました:)私は、「この」という参照を追加すると、TempObjectがGCされたときにGC'edを取得することに気付きました。しかし、私は "this"を参照しないで、静的なGeneratedClassが作成されることを意味するいくつかの用途を持っています。 TempObjectをGCしたときにこの静的参照を削除する方法はありませんか?もし存在すれば、どうすれば '_reference.Target!= null'が静的であってもそれを確実にすることができますか?言い換えれば、 "this"を参照する必要なしに、この問題の回避策をどのように作成できますか? – GTHvidsten
いいえ、削除する方法はありません。読み取り専用なので(たとえ何らかの形で反射を使用していたとしても)通常の静的メソッドを渡すのと同じ話です。ターゲットはnullで、あなたはそれで何もできません。 AddHandler(owner、(0)=> ....)明示的に "owner"オブジェクトを渡すことをお勧めします。あなたが弱い参照のためにそれを使用する - 使用する。これをオプションにすると、APIを悪用する可能性があるので、必要になると考えるかもしれません。 – Evk
私は今理解していると思います。好奇心のために、これはすべての匿名メソッド、またはイベントハンドラが参照を保持しているメソッドのみに発生しますか?これが私のイベントハンドラに関係なく発生した場合、これはC#.Netのメモリリークのようなものではありませんか? – GTHvidsten