单行:WeakReference的对A-LAMBDA事件处理程序事件、程序、WeakReference、LAMBDA

2023-09-03 13:04:51 作者:沒吃藥感覺自己萌萌噠

您可以看到缺点,以这一个班轮比其他的事实是它的多种用途会违反干原则?这似乎简单,但事实上,我还没有看到其他人提出这让我不知道是否有一个缺点吧。

Can you see downsides to this one-liner other than the fact that multiple uses of it would violate the DRY principle? It seems straightforward but the fact that I haven't seen others propose it makes me wonder if there's a downside to it.

的code此位将创建一个 WeakReference的以一个方法,然后注册一个事件处理程序调用参考的目标。

This bit of code creates a WeakReference to a method and then registers an event handler that invokes the reference's target.

SomeEvent += (sender, e) => ((Action)(new WeakReference((Action)ProcessEvent)).Target)();

谢谢, 本

Thanks, Ben

推荐答案

我不认为这个模式做你的期望。你持有一个引用当前对象,以prevent内存泄漏试图prevent事件?拉姆达EX pression将捕获的值,以评估中的processEvent (假设中的processEvent 是一个实例方法),所以你仍然有泄漏。这code是一样的做 SomeEvent + =(发件人,E)=>中的processEvent();

I don't think that pattern does what you expect. Are you trying to prevent the event from holding a reference to the current object so as to prevent memory leaks? The lambda expression will capture the value of this in order to evaluate ProcessEvent (assuming ProcessEvent is an instance method), so you will still have the leak. This code is the same as doing SomeEvent += (sender, e) => ProcessEvent();.

您可能会试图做一些更多的这样的(这也不是你想要的):

You may be trying to do something more like this (which also isn't what you want):

var reference = new WeakReference((Action)ProcessEvent);
SomeEvent += (sender, e) => ((Action)reference.Target)();

现在拉姆达EX pression将捕获的WeakReference,所以你不会有很强的参考。不幸的是,没有别的引用从创建的processEvent的代表,所以它会在下次GC删除,即使还活着。 (这也不会检查目标为空)。

Now the lambda expression will capture the WeakReference, so you won't have a strong reference to this. Unfortunately, nothing else is referencing the delegate created from ProcessEvent, so it will be removed on the next GC even if this is still alive. (This also doesn't check for Target being null).

您可以尝试这样的:

public EventHandler MakeWeakHandler(Action action, Action<EventHandler> remove)
{
    var reference = new WeakReference(action.Target);
    var method = action.Method;
    EventHandler handler = null;
    handler = delegate(object sender, EventArgs e)
    {
        var target = reference.Target;
        if (target != null)
        {
            method.Invoke(target, null);
        }
        else
        {
            remove(handler);
        }
    };
    return handler;
}

,然后用它是这样的:

and then use it like this:

SomeEvent += MakeWeakHandler(ProcessEvent, h => SomeEvent -= h);

这将保持的弱引用的processEvent的接收机,并会自动从已收集后的情况下,这应该作为事件经常引发只要prevent内存泄漏移除事件处理程序。

That will keep a weak reference to the receiver of ProcessEvent, and will automatically remove the event handler from the event after it has been collected, which should prevent memory leaks as long as the event is raised regularly.