实际使用System.WeakReference的(Practical use of System.

2019-08-17 23:10发布

我明白了什么System.WeakReference做,但我似乎无法把握是什么可能是有用的实际例子。 本身在我看来,阶级是,好了,一个黑客。 在我看来,还有其他的,解决其中的WeakReference是我见过的例子使用的问题的更好的方法。 什么是的,你真的得使用WeakReference的典型的例子? 我们不是试图让这种类型的行为,并使用这个类的?

Answer 1:

一个有用的例子是谁运行DB4O面向对象的数据库的家伙。 还有,在WeakReferences作为一种光缓存的:它会让你的对象在内存中,只要只能作为你的应用程序做,让你把一个真实的缓存之上。

另一个用途是在弱事件处理程序的执行。 目前,在.NET应用程序的内存泄漏的一个重要来源是忘记删除事件处理程序。 例如

public MyForm()
{
    MyApplication.Foo += someHandler;
}

看到这个问题? 在上面的代码中,MyForm的只要将永远为所有MyApplication在内存活保存在内存中活着。 创建10个MyForms,则全部关闭,你的10个MyForms仍然会在内存中,事件处理器保持活着。

输入的WeakReference。 您可以使用在WeakReferences使someHandler是弱事件处理程序MyApplication.Foo,从而修复您的内存泄漏建立一个弱事件处理程序!

这不只是理论。 从DidItWith.NET博客达斯汀·坎贝尔公布疲弱的事件处理程序的实现使用System.WeakReference。



Answer 2:

我用它来实现未使用的条目自动垃圾回收,其中高速缓存:

class Cache<TKey,TValue> : IEnumerable<KeyValuePair<TKey,TValue>>
{ Dictionary<TKey,WeakReference> dict = new Dictionary<TKey,WeakReference>();

   public TValue this[TKey key]
    { get {lock(dict){ return getInternal(key);}}
      set {lock(dict){ setInteral(key,value);}}     
    }

   void setInteral(TKey key, TValue val)
    { if (dict.ContainsKey(key)) dict[key].Target = val;
      else dict.Add(key,new WeakReference(val));
    } 


   public void Clear() { dict.Clear(); }

   /// <summary>Removes any dead weak references</summary>
   /// <returns>The number of cleaned-up weak references</returns>
   public int CleanUp()
    { List<TKey> toRemove = new List<TKey>(dict.Count);
      foreach(KeyValuePair<TKey,WeakReference> kv in dict)
       { if (!kv.Value.IsAlive) toRemove.Add(kv.Key);
       }

      foreach (TKey k in toRemove) dict.Remove(k);
      return toRemove.Count;
    }

    public bool Contains(string key) 
     { lock (dict) { return containsInternal(key); }
     }

     bool containsInternal(TKey key)
      { return (dict.ContainsKey(key) && dict[key].IsAlive);
      }

     public bool Exists(Predicate<TValue> match) 
      { if (match==null) throw new ArgumentNullException("match");

        lock (dict)
         { foreach (WeakReference weakref in dict.Values) 
            { if (   weakref.IsAlive 
                  && match((TValue) weakref.Target)) return true;
         }  
      }

       return false;
     }

    /* ... */
   }


Answer 3:

我使用的状态,同时要混入弱引用。 请记住,混入都是静态的,所以当你使用一个静态物体附着状态的非静态的,你永远不知道多久将是必需的。 因此,而不是保持一个Dictionary<myobject, myvalue>我把一个Dictionary<WeakReference,myvalue> ,以防止混入来自东西拖太久。

唯一的问题是,每次我做访问的时候,我还检查死引用并删除它们。 这并不是说他们伤害任何人,除非有成千上万,当然。



Answer 4:

有两个原因,为什么你会使用WeakReference

  1. 相反,声明为静态全局对象 :全局对象被声明为静态字段和静态字段不能GC'ed(垃圾收集),直到AppDomain是GC'ed。 所以,你的风险了内存不足的异常。 相反,我们可以换一个全局对象WeakReference 。 即使WeakReference本身声明为static,它指向的对象时,内存是低到将GC'ed。

    基本上,使用wrStaticObject代替staticObject

     class ThingsWrapper { //private static object staticObject = new object(); private static WeakReference wrStaticObject = new WeakReference(new object()); } 

    简单的应用程序,以证明静态对象是垃圾回收时的AppDomain是。

     class StaticGarbageTest { public static void Main1() { var s = new ThingsWrapper(); s = null; GC.Collect(); GC.WaitForPendingFinalizers(); } } class ThingsWrapper { private static Thing staticThing = new Thing("staticThing"); private Thing privateThing = new Thing("privateThing"); ~ThingsWrapper() { Console.WriteLine("~ThingsWrapper"); } } class Thing { protected string name; public Thing(string name) { this.name = name; Console.WriteLine("Thing() " + name); } public override string ToString() { return name; } ~Thing() { Console.WriteLine("~Thing() " + name); } } 

    从下面的输出注意staticThing在最后甚至后GC'ed ThingsWrapper即GC'ed时-是AppDomain是GC'ed。

     Thing() staticThing Thing() privateThing ~Thing() privateThing ~ThingsWrapper ~Thing() staticThing 

    相反,我们可以换ThingWeakReference 。 作为wrStaticThing可以GC'ed,我们需要,我已经离开了为简洁懒加载方法。

     class WeakReferenceTest { public static void Main1() { var s = new WeakReferenceThing(); s = null; GC.Collect(); GC.WaitForPendingFinalizers(); if (WeakReferenceThing.wrStaticThing.IsAlive) Console.WriteLine("WeakReference: {0}", (Thing)WeakReferenceThing.wrStaticThing.Target); else Console.WriteLine("WeakReference is dead."); } } class WeakReferenceThing { public static WeakReference wrStaticThing; static WeakReferenceThing() { wrStaticThing = new WeakReference(new Thing("wrStaticThing")); } ~WeakReferenceThing() { Console.WriteLine("~WeakReferenceThing"); } //lazy-loaded method to new Thing } 

    从下面的输出注wrStaticThing调用GC线程时GC'ed。

     Thing() wrStaticThing ~Thing() wrStaticThing ~WeakReferenceThing WeakReference is dead. 
  2. 对于那些费时初始化对象 :你不想被时间consusming给init被GC'ed对象。 你可以保留一个静态参考,以避免(与缺点从上面点),或者使用WeakReference



文章来源: Practical use of System.WeakReference