WeakReference - 我做得对吗?

发布于 2025-01-08 04:25:45 字数 905 浏览 0 评论 0原文

我有一个静态类,它公开一个事件:

public static class MyStaticClass
{
    static bool myBool= false;
    public static bool MyBool
    {
        get { return myBool; }
        private set
        {
            myBool= value;

            var handler = MyBoolChanged;
            if (handler != null)
                handler(null, null);
        }
    }

    public static event EventHandler MyBoolChanged;
}

然后我使用以下模式注册它:

class AnotherClass
{    
    WeakReference _me;

    public MyMethodInAnotherClass()
    {
        _me = new WeakReference(this);
        MyStaticClass.MyBoolChanged+= 
                (_me.Target as AnotherClass).MyMethodInAnotherClassCallback;    
    }

    private void MyMethodInAnotherClassCallback(some arguments)
    {
    }
}

我想要实现的是 MyStaticClass 仅在 AnotherClass 的实例存在时才执行处理程序 尚未处置(且尚未注销)。

I have a static class, which exposes a event:

public static class MyStaticClass
{
    static bool myBool= false;
    public static bool MyBool
    {
        get { return myBool; }
        private set
        {
            myBool= value;

            var handler = MyBoolChanged;
            if (handler != null)
                handler(null, null);
        }
    }

    public static event EventHandler MyBoolChanged;
}

And then I am registering to it using this pattern:

class AnotherClass
{    
    WeakReference _me;

    public MyMethodInAnotherClass()
    {
        _me = new WeakReference(this);
        MyStaticClass.MyBoolChanged+= 
                (_me.Target as AnotherClass).MyMethodInAnotherClassCallback;    
    }

    private void MyMethodInAnotherClassCallback(some arguments)
    {
    }
}

What I want to achieve is that MyStaticClass will only execute the handler if the instance of AnotherClass has not been disposed (and has not deregistered).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

感性 2025-01-15 04:25:45

我认为使用它的最好方法是忘记一个事件,并使用某种列表来代替;假设List;然后,您可以使用:

interface IFoo {
    void Bar(some args);
}

with:

static class Whatever {
    private static readonly List<WeakReference> items=new List<WeakReference>();
    public static void Add(IFoo foo) {
        if(foo != null) {
            var newRef = new WeakReference(foo);
            lock(items) { items.Add(newRef); }
        }
    }
    public static void DoIt(some args) {
        lock(items) {
           foreach(var item in items) {
              IFoo foo = item.IsAlive ? item.Target as IFoo : null;
              if(foo != null) foo.Bar(some args);
           }
        }
    }
}

以及附加机制来删除特定的 IFoo,并删除所有剩余的死 foo 待办事项。

然后,您只需要 AnotherClass : IFoo,以及应用您的回调的 Bar() 实现。

额外强调:静态集合(包括事件)是相当危险的;您必须偶尔进行某种清理以删除空项目,并在可能的情况下尝试立即取消订阅(例如,在 Dispose() 中)。举例来说:

public static void Remove(IFoo foo) {
    lock (items) { // also remove any dead debris
        items.RemoveAll(x => !x.IsAlive || x.Target == foo || x.Target == null);
    }
}

The best way I can see to use this is to forget about an event, and use some kind of list instead; let's say List<WeakReference>; you could then have:

interface IFoo {
    void Bar(some args);
}

with:

static class Whatever {
    private static readonly List<WeakReference> items=new List<WeakReference>();
    public static void Add(IFoo foo) {
        if(foo != null) {
            var newRef = new WeakReference(foo);
            lock(items) { items.Add(newRef); }
        }
    }
    public static void DoIt(some args) {
        lock(items) {
           foreach(var item in items) {
              IFoo foo = item.IsAlive ? item.Target as IFoo : null;
              if(foo != null) foo.Bar(some args);
           }
        }
    }
}

with additional mechanisms to remove a specific IFoo, and to remove all dead foos left todo.

Then you just need AnotherClass : IFoo, with a Bar() implementation that applies your callback.

Additional emphasis: static collections (including events) are fairly dangerous; you must have some kind of sweep occasionally to remove empty items, and try to unsubscribe promptly where possible (in Dispose(), for example). As an illustration:

public static void Remove(IFoo foo) {
    lock (items) { // also remove any dead debris
        items.RemoveAll(x => !x.IsAlive || x.Target == foo || x.Target == null);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文