Zamezení úniků paměti s připojeným Chování

hlasů
10

Jsem vytvořil „připojené chování“ v mém WPF aplikace, která mi dovoluje zpracovávat Enter kláves a přesunout na další ovládací prvek. Říkám to EnterKeyTraversal.IsEnabled, a můžete vidět kód na mém blogu zde .

Mým hlavním zájmem je, že teď budu mít nevracení paměti, protože jsem zpracování události PreviewKeyDown na UIElements a nikdy výslovně „odpojit“ událost.

Jaký je nejlepší přístup, aby se zabránilo tomuto úniku (pokud vůbec existuje)? Měl jsem vést seznam prvků Vedu, a vyvěste událost PreviewKeyDown v případě Application.Exit? Má někdo měl úspěch s připojenými chování ve svých vlastních aplikací WPF a přijít s elegantní řešení správy paměti?

Položena 18/08/2008 v 01:49
zdroj uživatelem
V jiných jazycích...                            


11 odpovědí

hlasů
4

Filozofická debata stranou, v pohledu na OP blogu, já nevidím žádný únik zde:

ue.PreviewKeyDown += ue_PreviewKeyDown;

Tvrdý odkaz ue_PreviewKeyDownje uložen v ue.PreviewKeyDown.

ue_PreviewKeyDownje STATICzpůsob a nemůže být GCed.

Žádný pevný odkaz ueje uložen, takže nic bránit tomu v bytí GCed.

Takže ... Kde je ten únik?

Odpovězeno 29/05/2011 v 19:56
zdroj uživatelem

hlasů
4

Ano, já vím, že v dávných dobách nevracením paměti jsou úplně jiný předmět. Ale s spravovaný kód, nový význam pojmu nevracení paměti může být vhodnější ...

Microsoft dokonce uznává to být nevracení paměti:

Proč Provádět WeakEvent vzor?

Posloucháním událostí může vést k nevracení paměti. Typický postup pro poslech na akci je použít syntaxi konkrétní jazyk, který přikládá obsluhu k události na zdroje. Například, v C #, že syntaxe je: source.SomeEvent + = nový SomeEventHandler (MyEventHandler).

Tato technika vytváří silnou referenci od zdroje události do posluchače událostí. Obvykle připevnění rutinu události pro posluchače, způsobí, že posluchač mít životnost objektu, který ovlivněna životnost objektu pro zdroj (není-li obsluha události je výslovně odstraněn). Ale za určitých okolností budete chtít životnost objektu posluchače, které mají být ovládány pouze jinými faktory, jako je například to, zda v současné době patří k vizuální stromu aplikace, a ne celou dobu životnosti zdroje. Kdykoliv zdroj objektu životnost přesahuje životnost objektu posluchače, běžná událost vzor vede k nevracení paměti: posluchač je udržován při životě déle, než bylo zamýšleno.

Používáme WPF pro klientské aplikace s velkými ToolWindows, které mohou být taženy klesla, všechny šikovný věci a vše kompatibilní s v XBAP .. Ale měli jsme stejný problém s některými ToolWindows která nebyla uvolněna .. To bylo způsobeno k tomu, že to bylo stále závislé na posluchače událostí .. teď to nemusí být problém, pokud zavřete okno a ukončete aplikaci. Ale pokud budete vytvářet velmi velké ToolWindows s množstvím příkazů, a všechny tyto příkazy dostane přehodnoceny znovu a znovu, a lidé musí používat aplikaci po celý den .. mohu vám říci, .. je to opravdu ucpává svou paměť a čas aplikace odpověď ..

Také jsem zjistil, že mnohem snazší vysvětlit můj manažer, který máme nevracení paměti, než vysvětlovat mu, že některé objekty nejsou odpadky shromažďují kvůli některým událostem, které potřebuje pro čištění)

Odpovězeno 18/08/2008 v 15:44
zdroj uživatelem

hlasů
4

Nesouhlasím DannySmurf

Některá rozložení objektů WPF mohou ucpat své paměti a vaše aplikace skutečně pomalé, pokud nejsou smetí shromáždilo. Takže mi připadá volba slov za správné, je netěsní paměti na objekty, které již používají. Čekáte, že položky, které mají být uvolněna, ale nejsou, protože tam je odkaz někde (v tomto případě v od rutiny události).

Nyní za skutečnou odpověď :)

Radím, abyste si přečetli tento článek WPF Performance na webu MSDN

Ne Odstranění rutiny událostí na objekty mohou ponechat objekty živý

Zástupce, že se objekt projde jeho případě je účinně odkaz na tento objekt. Proto zpracování událostí může držet objekty naživu déle, než bylo očekáváno. Při provádění vyčištění objektu, který byl registrován poslouchat událost objektu, je nezbytné odebrat delegáta před uvolněním objektu. Udržování nepotřebné objekty naživu zvyšuje využití paměti aplikace. To platí zejména tehdy, když objekt je kořenem logického stromu nebo vizuální stromu.

Radí vám nahlédnout do Slabý vzor událostí

Dalším řešením by bylo odstranit rutiny událostí, když jste udělal s objektem. Ale vím, že s připojenými vlastnostmi, které bod nemusí být vždy jasné ..

Snad to pomůže!

Odpovězeno 18/08/2008 v 09:39
zdroj uživatelem

hlasů
1

Vysvětlit svůj komentář k John Fenton poštou tady je moje odpověď. Podívejme se na následující příklad:

class Program
{
    static void Main(string[] args)
    {
        var a = new A();
        var b = new B();

        a.Clicked += b.HandleClicked;
        //a.Clicked += B.StaticHandleClicked;
        //A.StaticClicked += b.HandleClicked;

        var weakA = new WeakReference(a);
        var weakB = new WeakReference(b);

        a = null;
        //b = null;

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        Console.WriteLine("a is alive: " + weakA.IsAlive);
        Console.WriteLine("b is alive: " + weakB.IsAlive);
        Console.ReadKey();
    }


}

class A
{
    public event EventHandler Clicked;
    public static event EventHandler StaticClicked;
}

class B
{
    public void HandleClicked(object sender, EventArgs e)
    {
    }

    public static void StaticHandleClicked(object sender, EventArgs e)
    {
    }
}

Pokud máte

a.Clicked += b.HandleClicked;

a nastavit pouze b null V obou těchto pracích weakA a weakB zůstat naživu! Nastavíte-li pouze na null b zůstane naživu, ale ne (což dokazuje, že John Fenton je špatné říkat, že pevný odkaz je uložen v zprostředkovatele událostí - v tomto případě a).

To mě vedlo k nesprávnému závěru, že

a.Clicked += B.StaticHandleClicked;

by vedlo k úniku, protože i přesto, že instanci by být uchováván u statického psovoda. To není případ (otestovat můj program). V případě statické rutiny události nebo události je to naopak. Pokud napíšete

A.StaticClicked += b.HandleClicked;

odkaz bude omezen na b.

Odpovězeno 30/01/2015 v 15:33
zdroj uživatelem

hlasů
1

Už jste ačkoli zavádění „Slabá Pattern Event“ namísto pravidelných akcí?

  1. Slabá Pattern Event v WPF
  2. Slabé vzory událostí (MSDN)
Odpovězeno 18/08/2008 v 09:48
zdroj uživatelem

hlasů
1

@Nick Jo, ta věc s připojenými chování je, že z definice, že nejsme ve stejném objektu jako prvků, jejichž akce jste manipulaci.

Myslím, že odpověď spočívá v použití WeakReference nějak, ale já jsem neviděl žádný jednoduché ukázky kódu, aby mi to vysvětlit. :)

Odpovězeno 18/08/2008 v 02:51
zdroj uživatelem

hlasů
0

Pravda, pravda,

Máte pravdu, samozřejmě .. Ale existuje celá nová generace programátorů se narodili do tohoto světa, který nikdy dotknout neřízený kód, a věřím, že definice jazyk bude re-vynalézt sebe znovu a znovu. úniky paměti v WPF jsou tímto způsobem odlišným, než říci, C / CPP.

Nebo samozřejmě s mými manažery jsem se odkazovali na to jako úniky paměti .. Chcete kolegy kolegy I podle něj jako problému výkonu!

S odvoláním na Matta problém, může to být problém výkonu, který může být nutné řešit. Pokud jste právě použít několik obrazovek a uděláte ty obrazovky ovládá singletons, nemusí se tento problém vůbec).

Odpovězeno 18/08/2008 v 16:20
zdroj uživatelem

hlasů
0

@Arcturus:

... ucpat své paměti a vaše aplikace skutečně pomalé, pokud nejsou smetí shromáždilo.

To je nepřehlédnutelně jasné, a já nesouhlasím. Nicméně:

... jste netěsní paměti objektů, které již používají ... protože tam je odkaz na ně.

„Paměť je alokována na program, a tento program následně ztrácí schopnost přistupovat k němu z důvodu programových logických nedostatků“ (Wikipedia, „únik paměti“)

V případě, že je aktivní odkaz na objekt, který je váš program může přistupovat, pak podle definice není úniku paměti. Únik znamená, že objekt již není k dispozici (na vás nebo OS / rámce), a nebude uvolněno po celou dobu životnosti aktuální relace operačního systému . To není tento případ.

(Omlouvám se sémantickým nacista ... možná jsem trochu ze staré školy, ale únik má velmi specifický význam. Lidé mají tendenci používat „paměťový únik“ v těchto dnech nic neznamená, který spotřebovává 2kB paměti více, než chtějí. ..)

Ale samozřejmě, pokud nechcete uvolnit rutinu události, objekt je to spojovány nebude uvolněna, dokud nebude proces paměť je převzaty garbage collector při vypnutí. Ale toto chování je zcela očekává, na rozdíl od toho, co se zdají naznačovat. Pokud očekáváte, že objekt musí být kultivovaný, pak je třeba odstranit vše, co může udržet naživu odkaz, včetně obslužné rutiny.

Odpovězeno 18/08/2008 v 15:27
zdroj uživatelem

hlasů
0

Četla jsem váš příspěvek na blogu a myslím, že mám trochu zavádějící rady, Matta. Existuje-li skutečná paměti únik tady, pak je to chyba v rozhraní .NET Framework, a ne něco, co můžete být nutně opravit v kódu.

Co si myslím, vy (a plakát na svém blogu), jsou ve skutečnosti mluví o tu vlastně není úniku, ale spíše pokračující spotřeba paměti. To není totéž. Aby bylo jasno, unikly paměť je paměť, která je rezervován programem, pak opuštěný (tj ukazatel je vlevo visící), a které se následně nemůže být uvolněno. Vzhledem k tomu, paměť je řízena v .NET, je to teoreticky možné. Je však možné, aby program vyhradit stále větší množství paměti, aniž by odkazy na něj se dostanete mimo rozsah (a jsou způsobilé pro odvoz odpadu); však, že paměť není úniku. GC vrátí jej do systému, jakmile je váš program ukončí.

Tak. Chcete-li odpovědět na vaši otázku, já si nemyslím, že jste skutečně tady problém. Určitě nemají únik paměti, az kódu, nemyslím si, že budete muset starat, pokud jde o využití paměti pokračuje jeden. Tak dlouho, jak se ujistit, že nejste opakovaně přiřazovat tuto rutinu události, aniž by de-přiřazení (tj, že jste buď jen někdy ho jednou nastaven, nebo že jej odebrat právě jednou v každé době, jej přiřadit), který zdá se, že dělá váš kód by měl být v pořádku.

Vypadá to, že to je rada, že plakát na svém blogu se snaží, aby vám, ale on používal to alarmující práci „únik“, což je děsivá slova, ale mnoho programátorů zapomněli na skutečný význam v řízeném světě; to neplatí zde.

Odpovězeno 18/08/2008 v 04:40
zdroj uživatelem

hlasů
0

Ujistěte se, že událost se odkazovat prvky se v objektu jsou odkazování, stejně jako textová pole na ovládací prvek formuláře. Nebo, pokud to není možné zabránit. Vytvoření statického událost na globální třídy pomocníka a poté sledovat celkovou pomocnou třídu pro události. Pokud se tyto dva kroky nelze provést zkuste použít WeakReference, oni jsou obvykle ideální pro tyto situace, ale přicházejí s režií.

Odpovězeno 18/08/2008 v 01:58
zdroj uživatelem

hlasů
-1

Dobře, že (vedoucí bit) mohu určitě rozumět, a sympatizovat s.

Ale bez ohledu na to Microsoft nazývá, nemyslím si, že „nový“ definice je to vhodné. Je to složité, protože nežijeme v 100% spravovaného světě je (i když Microsoft rád předstírat, že děláme, Microsoft sám nežije v takovém světě). Když říkáte únik paměti, mohli jste na mysli, že program spotřebovává příliš mnoho paměti (to je definice uživatele), nebo že se podařilo reference nebude uvolněno až do výjezdu (jako zde), nebo že neřízený reference není řádně umyto up (to by byl skutečný únik paměti), nebo že neřízený kód volána ze spravovaného kódu netěsní paměti (jiný skutečný únik).

V tomto případě je jasné, co znamená „paměť únik“ prostředky, i když jsme je nepřesná. Ale to bude strašně únavné mluvit s některými lidmi, kteří volají každý nadměrné spotřebě, nebo selhání-to-sbírají únik paměti; a to je frustrující, když tito lidé jsou programátoři, kteří údajně vědí lépe. Je to docela důležité pro technické termíny mají jednoznačné významy, myslím. Ladění je tak mnohem jednodušší, když dělají.

Tak jako tak. Neznamenají proměnit tento do vzdušné-víla diskusi o jazyku. Jen říkám...

Odpovězeno 18/08/2008 v 16:09
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more