Как зайти в Даркнет?!
25th January, 01:11
6
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
895
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
914
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
906
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4351
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Практическое применение System.WeakReference
Я понимаю, что делает System.WeakReference , но то, что я не могу понять, - это практический пример того, для чего он может быть полезен. Сам класс мне кажется, ну, в общем, халтурой. Мне кажется, что есть и другие, лучшие способы решения проблемы, когда в примерах, которые я видел, используется WeakReference. Каков канонический пример того, где вы действительно должны использовать WeakReference? Разве мы не пытаемся уйти дальше от такого типа поведения и использования этого класса?
Один полезный пример-это ребята, которые управляют объектно-ориентированной базой данных DB4O. Там WeakReferences используются как своего рода легкий кэш: он будет держать ваши объекты в памяти только до тех пор, пока это делает ваше приложение, позволяя вам поместить реальный кэш сверху.
Другое применение было бы в реализации слабых обработчиков событий. В настоящее время одним из больших источников утечек памяти в приложениях .NET является забывание удалить обработчики событий. E.g.
public MyForm()
{
MyApplication.Foo += someHandler;
}
Видите в чем проблема? В приведенном выше фрагменте MyForm будет сохраняться в памяти навсегда, пока MyApplication будет жить в памяти. Создайте 10 MyForms, закройте их все, ваши 10 MyForms все еще будут находиться в памяти, поддерживаемой обработчиком событий.
Введите WeakReference. Вы можете построить слабый обработчик событий с помощью WeakReferences так, чтобы someHandler был слабым обработчиком событий для MyApplication.Foo, тем самым исправляя утечки памяти!
Это не просто теория. Дастин Кэмпбелл из блога DidItWith.NET опубликовал реализацию слабых обработчиков событий с использованием System.WeakReference.
Я использую его для реализации кэша, где неиспользуемые записи автоматически собираются в мусор:
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;
}
/* ... */
}
Я использую слабую ссылку для сохранения состояния в миксинах. Помните, что микшины статичны, поэтому, когда вы используете статический объект для присоединения состояния к нестатическому, вы никогда не знаете, сколько времени это потребуется. Поэтому вместо того, чтобы держать Dictionary<myobject, myvalue> , я держу Dictionary<WeakReference,myvalue> , чтобы миксин не тащил вещи слишком долго.
Единственная проблема заключается в том, что каждый раз, когда я делаю доступ, я также проверяю мертвые ссылки и удаляю их. Не то чтобы они причинили кому-то вред, если, конечно, их не тысячи.
Есть две причины, по которым вы будете использовать WeakReference .
Вместо глобальных объектов, объявленных как статические: глобальные объекты объявляются как статические поля, и статические поля не могут быть GC'ed (сбор мусора), пока
AppDomainне будет GC'ed. Так что вы рискуете out-of-memory исключениями. Вместо этого мы можем обернуть глобальный объект вWeakReference. Несмотря на то, что самWeakReferenceобъявлен статическим, объект, на который он указывает, будет 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 объед в самом конце, даже послеThingsWrapperэто - т. е. GC объед когдаAppDomainявляется GC объед.Thing() staticThing Thing() privateThing ~Thing() privateThing ~ThingsWrapper ~Thing() staticThingВместо этого мы можем обернуть
ThingвWeakReference. Поскольку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 вызывается.Thing() wrStaticThing ~Thing() wrStaticThing ~WeakReferenceThing WeakReference is dead.Для объектов, которые требуют много времени для инициализации : вы не хотите, чтобы объекты, которые требуют времени для инициализации init, были GC'ed. Вы можете либо сохранить статическую ссылку, чтобы избежать этого (с минусами от точки выше), либо использовать
WeakReference.