user604613
user604613

Reputation:

WeakReference - Am I doing it right?

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).

Upvotes: 1

Views: 540

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1062780

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);
    }
}

Upvotes: 1

Related Questions