[ CallMeSaMaster @ 07.06.2009. 21:37 ] @
Pozdrav svima,

Napravio sam jednu applikaciju koja mi nenormalno trosi memoriju...U cemu je problem?

Na jednoj formi imam TableLayoutPanel. U taj panel zavisno od broja upisa u bazi(recimo Imena uposlenika) pri startu forme, mi se dinamicki kreiraju Buttons.
Za svaki taj Button sam napravio Handler, znaci koliko god ima dugmadi, dodaje se i Buttonhandler.

Klikom na to dugme, u drugom TableLayoutPanel-u, se takodjer dinamicki generisu buttons, recimo organizacione jedinice svakog uposlenika. Znaci svaki uposlenik moze imati vise organizacionih jedinica, i zavisno od njihovog broja, za svaku jedinicu se genrise novi button.

Problem nastaje u sledecem: Kada u prvom Panelu klikam na Uposlenike(skacem sa jednog na drugi), svaki put mi se u drugom panelu mijenja content tj generisu mi se buttons. Medjutim svaki taj click na Uposlenika uzrokuje da applikacija trosi memoriju, tako da Memory Usage za tu app stalno raste.
Ako zatvorim tu formu, nista se ne desi, a ja bih ocekivao da se ta memorija smanji(isprazni) nakon sto sam zatvorio formu.

Pokusavao sam razne dispose, ali nista ne pomaze. Evo dole dio koda koji se izvrsava nakon sto kliknem na user-a, pa ako moze neko da mi pomogne kako da rijesim taj problem.

Znaci, kada se pozove na izvrsavanje ovaj donji code, svaki put memmory Usage poraste. Dispose sam ovdje(u ovom code) namjerno izostavio jer ionako ne radi.

App je radjena u Vb.Net 2005,
Za buttons koristim KryptonToolkit dll, znaci third Part control, ljepse izgledaju. Da li to moze biti uzrok???

Code:

Private Sub btnArrayClick(ByVal sender As System.Object, ByVal e As EventArgs)

        TableLayoutPanel2.Controls.Clear()

        Dim myConnection As SqlConnection = New SqlConnection(PopCodexAB00FAD5BB(Host1, Host2))
        Dim myCommand As SqlCommand = New SqlCommand("Jedinice", myConnection)
        Dim i As Integer = 0
        Dim da As SqlDataAdapter = New SqlDataAdapter
        Dim ds As New DataSet
        Dim url As String = "C:\Program Files\Orga\Orga\slike\"

        myCommand.CommandType = CommandType.StoredProcedure
        myCommand.Parameters.Add(New SqlParameter("@id", SqlDbType.Int)).Value = sender.tag

        da.SelectCommand = myCommand
        da.Fill(ds, "Jedinice")

        Dim btn(ds.Tables("Jedinice").Rows.Count) As KryptonButton

        For Each row As DataRow In ds.Tables("Jedinice").Rows

            i = i + 1

            btn(i) = New KryptonButton
            btn(i).Text = row(1).ToString
            btn(i).StateCommon.Content.ShortText.TextH = PaletteRelativeAlign.Far
            btn(i).ForeColor = Color.White
            btn(i).Tag = row(0)

            btn(i).Name = "Button" + i.ToString()
            btn(i).Size = New Size(178, 68)
            btn(i).StateCommon.Content.ShortText.Font = New Font("Ariel", 9, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point)
            btn(i).Values.Image = Image.FromFile(url + row(4))
            btn(i).StateCommon.Content.Image.ImageH = PaletteRelativeAlign.Near
            btn(i).PaletteMode = PaletteMode.SparkleBlue
            btn(i).ButtonStyle = ButtonStyle.Standalone

            TableLayoutPanel3.Controls.Add(btn(i))
            TableLayoutPanel3.AutoSize = True

            AddHandler btn(i).Click, AddressOf Me.btnArray1Click

        Next
End Sub
[ mmix @ 07.06.2009. 22:29 ] @
Na kom OSu meris potrosnju memorije i kako?
[ CallMeSaMaster @ 07.06.2009. 22:32 ] @
OS WIN XP SP2
Taskmanager kao mjerilo, zasad dovoljno
[ vbbojan @ 07.06.2009. 22:54 ] @
Ocigledno je da imas kreirane reference na tvoje buttone, a kojih nisi svestan.

Konkretno kod tebe su te reference kreirane prilikom registrovanja eventa - addhandler.

Jednostavno, prilikom zatvaranja forme pozovi removehanler za svaki button, nesto ovako:

Code:


For Each kb as KryptonButton in btn

   RemoveHandler kb.click, AddressOf Me.btnArray1Click

Next



Da odma' vidis dal ovo radi forsiraj garbage collect.
Ako imas puno memorije na raspolaganju, CLR ga ne potpaljuje bas cesto.


Pozdrav i javi dal' radi.
[ CallMeSaMaster @ 07.06.2009. 23:14 ] @
Pozzz,

probao, ne radi.
Ne konta ovaj For Each --> btn, jer nema pojma sta je to
[ mmix @ 07.06.2009. 23:30 ] @
Citat:
CallMeSaMaster: OS WIN XP SP2
Taskmanager kao mjerilo, zasad dovoljno


Zato sam te i pitao. Taskmanager nikad nije dovoljno dobro merilo za koriscenje memorije u .NET-u, naroito na XP-u. Ako na sistemu imas dovoljno RAMa i ako GC zakljuci da mu je jeftinije da prosiri heap nego da oslobodi sopstvenu memoriju kroz Gen2 cleanup potrosnja memorije ce rasti. Posto vreme zivota tvojih objekata i nije tako kratko, sasvim je sigurno da su svi oni dospeli do Gen2 ili large-object nivoa. Kad GC zakljuci da ce mu dalje sirenje biti skuplje od ciscenja pocistice Gen2 ali i dalje NECE osloboboditi memoriju i cuvace je za slucaj novog sirenja, zbog toga ti ni rucni collect nece pomoci. Tek kad i ako ostale aplikacije na sistemu naprave pritisak na memoriju i .NET runtime dobije zahtev za smanjivanjem footprinta bice toliko velikodusan da memoriju vrati .

Jedini efektivan nacin da otkrijes da li imas ozbiljan memory leak je da pratis interno stanje GC memorije unutar aplikacije a tu je taskmenadzer na XPu neprecizan jer ne prikazuje private bytes po default-u vec working set (to je uvedeno tek na visti koja po defaultu prikazuje private set). Sve ostale GC parametre mozes da pratis iz performance monitora (da bi npr video koliko cesto se desava Gen2 cleanup i kako "dise" heap). Prvo sto bih ja pogledao su Gen2 HEAP size i Gen2 collection counter. Ako se Gen2 desava a Gen2 HEAP i dalje raste onda imas problem.

Baci pogleda na ovaj i ovaj i slicne tekstove za vise detalja o memoriji i kako se problemi resavaju,.

[ vbbojan @ 07.06.2009. 23:31 ] @
Aha!
btn ti je tvoj array buttona, ali sad vidim da je on dostupan samo iz
btnArrayClick procedure, resenje bi na primer bilo da provrtis sve kontrole
iz TableLayoutPanel3 i tu da odradis posao, na primer:

Code:


For Each ctrl in TableLayoutPanel3.Controls

   If TypeOf ctrl Is KryptonButton then
      RemoveHandler CType(ctrl, KryptonButton).Click, AddressOf Me.btnArray1Click
   End If

Next



Pozdrav
[ CallMeSaMaster @ 08.06.2009. 09:12 ] @
@mmix Hvala za pojasnjenje

@vbbojan
Nazalost en pomaze...:(
[ CallMeSaMaster @ 08.06.2009. 13:17 ] @
Pozdrav,

upravo sam testirao da na formu napravim obicna dugmad a ne KryptonButtons i da ne koristim njihovu dll. Za cudo, ali sa normalnim dugmadima
aplikacija ni u pola ne trosi toliko memorije. Cak sam i dispose izostavio sve iz coda i opet radi bolje nego sa tim dugmadima.

Da li je moguce da ove third part controle ovako zezaju?

Da li neko ima neku kolekciju dugmadi/Controla free a da rade normalno? Ova defaultna su malo bezze a ne gubi mi se vrijeme da pravim svoja....
[ vbbojan @ 08.06.2009. 14:50 ] @
Generalno third party kontrole znaju da budu žderači resursa,
to je cena koja mora da se plati za njihov lep izgled.

Moguće je da je sve u redu sa tvojim krypton kontrolama, a kao što
ti je mmx već detaljno objasnio, moguće je da imaš više nego dovoljno
memorije pa se CLR jednostavno razbaškario, a kako to sistemu ne smeta
onda on i ne cisti za sobom.

Naravno, uvek postoji mogucnost da sama kontrola ima bug i da ne
oslobađa resurse.

U svakom slučaju proanaliziraj situaciju po mmx uputstvu, možda
zaključiš da je sve u redu.

U aplikacijama kojima se ja bavim, (koristim devexpress kontrole)
zauzeće memorije zna da dogura i do 90 - 100 Mb za par otvorenih
formi (doduše koristim skinove) i onda obično ostane na toj
cifri, ma šta dalje radio.

Opet uporedi to sa na primer mozilla firefoxom koji za nekoliko tabova
zna da proguta i 200-300Mb ... ili na primer skype-om gde običan
"telefon" jedva naguraše u 50-60 Mb

Naravno, da bi petljao sa ovakvim stvarima (ako već nisi) moraš se upoznati
sa osnovnim principima memory managementa CLR-a
heapovi, large heapovi, generacije objekata, garbage collecting ...


Pozdrav












[ CallMeSaMaster @ 08.06.2009. 15:03 ] @
Pozz,

Sve je meni to jasno.Po ovome sto sam gledao sve je ok. Medjutim ako ja 1000 kliknem na jednoj formi, zauzece memorije ce da raste u beskrajnost. A ta opcija da ce neko kliknuti 1000x realno postoji.

Druga stvar je da mi se to ne desava sa klasicnim .net Kontrolama. Kao sto i sam kazes, raste do nekog nivoa, ali onda tu ostaje.

Ovaj Krypton je nudio lijep izgled ali ja nisam spreman da na ustreb toga paltim tu cijenu....

Tako da moram dalje da experimentisem :)

Hvala u svakom slucaju
[ CallMeSaMaster @ 12.06.2009. 15:52 ] @
Pozdrav jos jednom,

nakon istrazivanja dosao sam do zakljucka da samo jedna stvar rijesava moj problem: Format C:/

Zezam se!!!

Naime jedino sta u mom slucaju radi je sledece:

Code:

        Try
            Dim Mem As Process
            Mem = Process.GetCurrentProcess()
            SetProcessWorkingSetSize(Mem.Handle, -1, -1)
        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try


Ovo periodicno oslobadja moju memoriju i radi sasvim ok. Nazalost na netu sto sam naso, misljenja su podijeljena oko prednsoti i mana.
Prema tome, bio bih zahvalan ako neko ima slicnog iskustva da mi kaze jeli ovo ok ili ne? Kakve posljedice mogu da ocekujem i sl.

Hvala na odgovorima
[ mmix @ 12.06.2009. 16:22 ] @

Shrinkovanje working seta ce ti smanjiti footprint ali ce zato usporiti tvoj program jer ce morati da ceka da mu OS ponovo "naduva" working set pri svakom pristupu memoriji koja je izbacena iz RAM-a i ako je heap u aktivnoj upotrebi opet ce se naduvati na staru velicinu. Apsolutno nemas potrebe da ovo radis, ako sistemu zafali memorija smanjice ti sam working set.
[ CallMeSaMaster @ 12.06.2009. 23:41 ] @
@mmix

ali upravo to i jest moj problem. Sistem uzima memoriju koja mu uopce nije potrebna.Svaki klik na neki button iz gore navedenog coda uzima i do 2MB!!!! To je zalosno.
A druga stvar ja sam klikao i klikao(testa radi - sta ce biti akda bude) i u jednom trenutku appliakcija odleti(crkne, sve zastopa ili nazovi kako hoces) jer ovo cudo nikad ne oslobodi memoriju.
Jednostavno sam primoran da radim ovu bljuvariju, koja mi se iskreno i ne svidja bas jer ne znam 100% koji ce biti impact. Medjutim rjesava moj problem.
I ne primjetim nista cudno kada ponovo klikam ta ista dugmad, mislim na brzinu i sl. Radi normalno.

Jednostavno ne izlazim na kraj sa ovim. I kao sto sam rekao, default buttons iz .NET-a rade normalno, memorija se lagano ali kontinuirano oslobadja. Medjutim kada koristim ove buttone, javlja se taj problem.
Pisao sam i kompaniji koja ih razvija i kazu da ne bi trebalo da se to desava...Ne moguce da mi je code toliko los da je to problem. Bar bi mi neko od vas rekao ne radi s eto tako ili nesto sl.

Ne znam sta jos da radim. Iskreno default buttons i nisu cemu...
[ mmix @ 13.06.2009. 00:32 ] @
Da, ali ako imas leak ovo nije resenje, i da ne radis redukciju working set-a na kraju bi sistem sam poceo da ti trimuje working set i da odvlaci stranice u page file kad ostalim aplikacijama zafali, to sto si ti smanjio working set nije izbrisalo te page-ove iz virtuelnog adresnog prostora, samo ih je prebacilo u page file koji ce onda da se puni kontinuirano dok se ne napuni skroz i onda ces opet da dobijes outofmemory exception isto kao sto bi dobio i da nisi rucno trimovao working set. To je posledica cinjenice da je (uprosceno) ukupna memorija na sistemu = fizicka memorija+page file, ako je alociras odredjenim tempom a ne oslobadjas (sto je memory leak) napunice se posle X alokacija, dal ces tokom tih X alokacija da imas smanjeni working set ili ces imat veliki working set nije mnogo vazno, X ce doci pre ili kasnije. Sta vise trimovanjem working seta usporavas aplkaciju jer i oni page-ovi koji su u realnoj upotrebi posle trimovanja moraju da se ucitaju nazad u working set. Vrlo su retke situacije u kojima ti imas potrebu da trimujes working set na (-1, -1) a resavanje memory leak-a sigurno nije deo te price.

Ali ja i dalje mislim da ovo ne znaci da ti imas memory leak, veoma je moguce da ti jednostavno imas puno rama i da se aplikacija siri i ne poziva LOH cleanup, ne znam ni da li si uopste probao da iscitavas metriku po onim clancima sto sam ti dao. Factory dugmici mozda rade drugacije zato sto su instance manje i ne odu u LOH.
[ CallMeSaMaster @ 13.06.2009. 00:50 ] @
Ovako imam HP Notebook nx7400, Intel CPU T2400 1, 83 GHz sa 2 GB Rama.

To sto ti govori stoji, samo se ne slazem u jednoj stvari a to je da nemam memory leak.
Ja mislim da imam, i te kako da imam, jer kao sto vec kazem aplikacija zatrokira cijeli com u nekom trenutku...
[ mmix @ 13.06.2009. 04:10 ] @
Onda profiler u ruke i vidi koji objekti ti se gomilaju tokom rada aplikacije. Obicno u takvim situacijama jedna ili par klasa prednjace daleko daleko ispred ostalih.

Imas dosta i specijalizovanih profilera, npr http://memprofiler.com/ ciji trial ti traje 14 dana sto je dovoljno vremena da resis svoj problem.
[ CallMeSaMaster @ 13.06.2009. 11:57 ] @
@mmix

Iskreno, pokrenuo sam profiler ali posto nisam dosad koristio ne mogu reci da mi je sve jasno iz ovoga. Ako mogu da te zamolim da prokomentarises
slike koje sam nakacio a dobio sam ih iz profilera.

Slika je iz 3 dijela...

http://img188.imageshack.us/gal.php?g=36291012.jpg
[ mmix @ 13.06.2009. 13:50 ] @
Po ovome i nemas neki problem, bar ne sa nedisposovanim idispose objektima, sve sto je na ovoj listi je sica.

Uradi sledece:

prebaci filter na "with live instances" i uradi snapshot, onda maltretiraj aplikaciju dok ne krene da trokira, onda uradi novi snapshot. Uporedi ta dva snapshot-a a sortiraj listu po Delta polju (sortirano na dole). ako imas zivih leakovanih objekata imacas i veliki pozitivni delta. Za sada ignorisi kernel elemente u listi.
Ako nadjes neku .NET klasu koja ima drastican rast u Delta, rclick na nju i Show Type Details i dobices stack trace-ove lokacija u kojima su instance kreirane. Pa ajd da vidimo dal leak-ujes te dugmice

Ako tu nema leak-a to i dalje ne znaci da nema bug-a, moracemo onda da proverimo unmanaged resurse, mozda njihov dispose ne radi kako treba (mada mi je to sumnjivo, mislim da bi to neko primetio davno pre tebe). Al da bi uopste to uradili, idi na "native memory" tab i ukljuci "show memory differences between snapshots" i reci za koliko se sta povecalo u physical i commited, ne moras da ides duboko u listu, samo sve tri stavke u root-u i prvi nivo stavki unutar "Private" (managed heaps, stacks, itd), ne mora dublje od toga. Pa da vidimo koliko se naduvala memorija.

U prinicpu mozes i da snimis i zipuje pfsession fajl pa okaci ovde ili na neku dostupnu lokaciju, da ne prepricavas rezultate.

PS: Radi Gen0 snapshots, cisto da log ne sadrzi sve one sitne objekte ciji zivotni vek ne bi presao Gen0.
[ CallMeSaMaster @ 13.06.2009. 16:56 ] @
Pozdrav,

evo okacio sam snapshots pa ako mozes pogledaj.

1 File je na pocetku

2 File je kad je sve trokiralo

3 File je Gen0

Nadam se da ce to biti dovoljno...

http://rapidshare.com/files/244124381/Snaphots.rar.html
[ mmix @ 13.06.2009. 19:28 ] @
ok, nismo se razumeli ali nije ni vazno jer sam se snasao za pocetak. Za ubuduce, kad profilujes aplikaciju to radis u okviru jedne sesije sa vise snapshotova, ne zasebna sesija za svaki snapshot jer onda ne mozes da poredis snapshote i otezana je analiza jer ne moze da se eliminise ono sto je vec postojalo (delta nije dobar). Isto kad sam rekao gen0 snapshot to je znacilo da i prvi i drugi snapshot budu preko onog dugmeta sa Gen0 (pored ovog koje pritiskas), ne da kreiras poseban gen0 snapshot, to dugme samo znaci da prvo uradi gen0 kolekciju i onda tek da uradi snapshot, sto vodi ka smanjenju suma a i velicine session fajla.

Elem,

tvoja muka lezi u krypton buttonu defintiivno, pronasao sam 8000 instanci dugmica, oni sami po sebi nisu toliki problem (managed data je manje od 2 mb) ali posto za svaki ucitavas sliku onda to vuce unamanaged GDI resurse koje medjutim nisi ukljucio u analizu pa ne mogu da vidim da li je to zasluzno za raspad sistema.
Sad treba da uradis sledece. Ubaci dispose u igru, pre nego ti stari dugmici odu iz scope-a disposuj ih (vidim u logu da nisu disposovani) i uradi jos jednu sesiju sa dva snapshota (posle starta, i posle maltertiranja) i daj mi fajl, ali sad podesi ove opcije u session wizardu:

- dispose tracker - YES
- real time - NO
- instance data - NO
- heap utilization - YES
- unmanaged resource tracker - YES

to ce malo i ograniciti sesson file a dace informacije koje trebaju, znaci oba snapshota u okviru iste sesije, please.

[ CallMeSaMaster @ 13.06.2009. 23:40 ] @
Pozdrav,

nazalost ima jedan mali problem sa tim dispose-om:Ako pogledas code koji sam na pocetku teme post-o,
primjetit ces sledece:

Code:

        For Each row As DataRow In ds.Tables("Jedinice").Rows

            i = i + 1

            btn(i) = New KryptonButton
            btn(i).Text = row(1).ToString
            btn(i).StateCommon.Content.ShortText.TextH = PaletteRelativeAlign.Far
            btn(i).ForeColor = Color.White
            btn(i).Tag = row(0)

            btn(i).Name = "Button" + i.ToString()
            btn(i).Size = New Size(178, 68)
            btn(i).StateCommon.Content.ShortText.Font = New Font("Ariel", 9, 
                        System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point)
            btn(i).Values.Image = Image.FromFile(url + row(4))
            btn(i).StateCommon.Content.Image.ImageH = PaletteRelativeAlign.Near
            btn(i).PaletteMode = PaletteMode.SparkleBlue
            btn(i).ButtonStyle = ButtonStyle.Standalone

            TableLayoutPanel3.Controls.Add(btn(i))
            TableLayoutPanel3.AutoSize = True

            AddHandler btn(i).Click, AddressOf Me.btnArray1Click
        Next



Kao sto vidis, dinamicki se dodaje handler za svaki button. Eh sada, nisam bas siguran ako da uklonim handler za btn(i), jer nemam to "i".
Dispose bih radio na izlazu sa forme, ali nazalost,
iako nisam probo, siguran sam da ce compiler javiti error jer ne zna sta je to "i".
Iskreno ni ja ne znam kako da ga dispose, jer ako stavim ovako, past ce...

Code:

RemoveHandler btn(i).Click, AddressOf Me.btnArray1Click


Kako da ga dispose???

[Ovu poruku je menjao mmix dana 14.06.2009. u 01:08 GMT+1]
[ mmix @ 14.06.2009. 00:32 ] @
Vrlo prosto, tamo gde ih inace izbacujes iz scope-a, a to je tamo gde pozivas TableLayoutPanel3.Controls.Clear(), samo sto mene ne interesuje removehandler, Eventhandler instanca koju kreiras sa AddHandler je ciklicna (pripada button-u na koji pokazuje), tako da kad cleanup pokupi button pokupice i taj event handler, ako bas hocs da budes koser mozes da dodas i removehandler, ali mislim da to nije presudno, vazniji je dispose.

samo sto izgleda na osnovu logova da kryptonbutton dodatno kreira evente u nekim svojim internim strukturama koje zive duze od dugmeta i da te reference sprecavaju cleanup nakon sto nullujes svoj pointer, sto pretpostavljam da ce button.dispose da resi. Posto ta event invocation lista pripada svom posebnom GC rootpath-u ne mogu da znam dal nesto drzi objekat u zivotu legalno ili bagovito pre nego sto uradis dispose, verovao ili ne tvoj jedan button pripada 22 razlicitih rootpath-ova, tj nalazi se u 22 razlicite GC strukture, sto je malo mnogo bar po nekom mom iskustvu, treba sve to pocistiti (al to nije tvoj problem, vec onog ko je pisao krypton). Tek kad button uradi svoj cleanup mogu da vidim da li je neki root-path preostao ili su svi nullovani i objekat je otisao na kolekciju.

Dakle ubaci sledeci kod umesto TableLayoutPanel3.Controls.Clear()

Code:

For Each c in TableLayoutPanel3.Controls
   c.Dispose()
Next
TableLayoutPanel3.Controls.Clear()


ovo predvidja da u TableLayoutPanel3 drzis samo dugmice....
[ vbbojan @ 14.06.2009. 00:40 ] @
Uf! Ajd' ovako, array ti i ne treba ...

Code:

       Dim btn as KryptonButton
       Dim i as integer = 0

       For Each row As DataRow In ds.Tables("Jedinice").Rows

           i += 1

           btn = New KryptonButton
           btn.Text = row(1).ToString
           btn.StateCommon.Content.ShortText.TextH = PaletteRelativeAlign.Far
           btn.ForeColor = Color.White
           btn.Tag = row(0)

           btn.Name = "Button" + i.ToString()
           btn.Size = New Size(178, 68)
           btn.StateCommon.Content.ShortText.Font = New Font("Ariel", 9, 
                       System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point)
           btn.Values.Image = Image.FromFile(url + row(4))
           btn.StateCommon.Content.Image.ImageH = PaletteRelativeAlign.Near
           btn.PaletteMode = PaletteMode.SparkleBlue
           btn.ButtonStyle = ButtonStyle.Standalone

           TableLayoutPanel3.Controls.Add(btn)
           TableLayoutPanel3.AutoSize = True

           AddHandler btn.Click, AddressOf Me.btnArray1Click

        Next


Da pocistis za sobom, recimo ovako (ideju si mogao dobiti već iz posta sa početka teme):

Code:


       Dim kb as KryptonButton

       For Each ctrl in TableLayoutPanel3.Controls

           If TypeOf ctrl Is KryptonButton then
               kb = CType(ctrl, KryptonButton)
               RemoveHandler kb.Click, AddressOf Me.btnArray1Click
               TableLayoutPanel3.Controls.Remove(kb)
               kb.Dispose
           End If

        Next



Pozdrav

Edit, malo zakasnih ...
[ CallMeSaMaster @ 14.06.2009. 09:05 ] @
Pozz,

evo napravio sam dva snapshota Gen0 sa dispose kao sto ste opisali.

http://rs428.rapidshare.com/files/244345831/Session_4.rar

Nazalost nista se nije promijenilo.

Da li bi recmi pomoglo ako bi ja negdje upload demo aplikacije pa da pogledate?

[ mmix @ 14.06.2009. 14:32 ] @
Nije se nista promenilo zato sto nista nisi dispose-ovao, pogledaj sliku i videces da je dispose kolona prazna, sto znaci da nijedan od dinamicki kreiranih dugmica nije dispose-ovan; da nemas jos negde TableLayoutPanel3.Controls.Clear()? Ta kolekcija ne sme da se prazni sa Clear() bez da se elementi disposuju prvo, to je obavezno u tvom slucaju jer na nivou aplikacije postoji root instanca klase KryptonManager koja drzi zivu instancu svih krypton kontrola na formi (koliko vidim zbog skinovanja) i mislim da je to rootpath koji sprecava autoamtsku finalizaciju buttona (na slici desno).


Dalje, tebe definitivno slike umlacuju, na kraju imas 16800 image objekta cije su bitmape lockovane u memoriju, tebi na kraju ne ponestane virtuelnog adresnog prostare vec mesta u fizickoj memoriji za smestanje slika (onih iz \program files\@Caffee\@Caffee\slike, npr balantine2.jpg, campari.jpg prednjace). To ce definitivno dispose da resi ako krypton nije bagovit.

[ vbbojan @ 14.06.2009. 19:17 ] @
Pazi kad me nije mrzelo da skinem Krypton Suite ... i da malo pogledam.
Prvo sto sam uocio je da sam te pogresno savetovao oko dispose buttona iz panela.

Naime, to ne radi kako treba, jer iterator prodje samo preko pola objekata u kolekciji,
sto se moze videti iz sledeceg:

Code:


        Dim ctrlprocessed As Integer = 0

        Debug.WriteLine("Broj kontrola u panelu pre ciscenja: " & Me.TableLayoutPanel1.Controls.Count.ToString)

        For Each ctrl In Me.TableLayoutPanel1.Controls

            ctrlprocessed += 1
            ctrl.Dispose()

        Next

        Debug.WriteLine("Broj kontrola kroz koje je prosla petlja: " & ctrlprocessed.ToString)
        Debug.WriteLine("Broj kontrola u panelu posle ciscenja: " & Me.TableLayoutPanel1.Controls.Count.ToString)



Sto ce reci, iteracija kroz kolekciju i promena broja elemenata iste, se ne zavrsava sretno.
Previd, sa moje strane, ali i dobar primer kako nesto sto na prvi pogled radi dobro u stvari i ne radi.

No, da bi stvarno prosli kroz kolekciju kontrola u panelu treba nam nesto na primer ovako:

Code:


        Dim ctrlprocessed As Integer = 0

        Debug.WriteLine("Broj kontrola u panelu pre ciscenja: " & Me.TableLayoutPanel1.Controls.Count.ToString)

        Dim ctrlArr As ArrayList = New ArrayList(Me.TableLayoutPanel1.Controls)

        For Each ctrl In ctrlArr

            ctrlprocessed += 1
            ctrl.Dispose()

        Next

        Debug.WriteLine("Broj kontrola kroz koje je prosla petlja: " & ctrlprocessed.ToString)
        Debug.WriteLine("Broj kontrola u panelu posle ciscenja: " & Me.TableLayoutPanel1.Controls.Count.ToString)


I sad konacno imamo metod koji stvarno radi dispose ... kako treba

Probaj ovako.

I da, ovoliki broj slika je stvarno problematican, ako je bas neophodno da ih bude ovoliko,
potrebno je optimalnije resenje.

Pozdrav i javi kako ide dalje


[ CallMeSaMaster @ 14.06.2009. 21:07 ] @
@mmix

Hvala na analizi, sad sam gledao bez slika i niej toliko strasno. Ali moj problem je da jednostavno mroam imati sliku na buttonu.
Dali mozes da mi obajsnis koji je najbolji nacin odnosno gdje da cuvam te objekte(slike)? Da li mozda u bazi(koristim Sql Server 2005)?
Trenutno drzim na disku(znam da nije najbolja solucija, znao sam to i raniej ali se ni u snu nisam nadao da ce me toliko kostat)


@vbbojan

Hvala i tebi. To sto se samo pola kontrola dispose, sam i ja jutros primjetio. Nazalost nisam stigao napisati jer sam morao krenuti na put.
Sa novim kodom sam takodjer probao, radi dobro, memorija takodjer radi kako ocekujem. Medjutim kada u tablelayoutu radi dispose, sve mi treperi.Sto mi se nikako svidja. Imas li neki prijedlog? Probao sam da suspendujem layout pa da resume ali ne ide bas....
[ Igor Gajic @ 14.06.2009. 21:19 ] @
Nemoj ici kroz kolekciju sa ovom metodom:

Code:


        For Each ctrl In Me.TableLayoutPanel1.Controls

            ctrlprocessed += 1
            ctrl.Dispose()

        Next



idi sa ovom(C# ali mislim da ces se snaci):
Code:

while(this.TableLayoutPanel1.Controls.Count>0)
{
ctrlprocessed+=1;
TableLayoutPanel1.Controls[0].Dispose();
}


Razlog, modifikuje se kolekcija kada uradis Dispose() ali to uradi tiho i ne upozorava te.
[ CallMeSaMaster @ 14.06.2009. 22:03 ] @
Pokusao, i opet isto. Treperi i dalje...
[ mmix @ 14.06.2009. 22:09 ] @
@Igor, u pravu si, i ja sam zaboravio na ovaj idiotizam Control objekta, ako su vec toliko prekrsili sopstvenu semantiku onda su bar mogli da stave neki fleg u Clear metod pa da ti parent disposeuje kontrole ako hoces. Ima tu mnogo nelogicnosti.

@CallMeSaMaster:

slike mozes i da kesiras pa da kloniras po potrebi, dobices na brzini sto ne moras svaki put da ih ucitavas sa diska. Ali ti i dalje to ne reseava tvoj problem, dal ces klonirati bitmapu ili ces je ucitati sa diska ili ces je ucitati iz SQL-a opet zauzima memoriju jer GDI radi sa bitmapama u fizickoj memoriji, ako ne disposujes bitmap objekat GDI handle ce ostati zajedno sa bitmapom. Dispose ce osigurati da se u dispose lancu oslobodi i slika iz GDI-a.
form ti treperi zato sto dispose button-a poziva remove u TableLayoutPanel koji posle svake iteracije poziva repaint. Treba da koristis suspend layout na nivou forme, pre nego udjes u dispose petlju i da uradis resume na kraju kad je TableLayoutPanel ispraznjen i onda napunjen sa novim dugmicima (u prevodu, na pocetku i kraju btnClick metoda)
[ CallMeSaMaster @ 14.06.2009. 22:21 ] @
Ok, sada radi to sa dispose, jer mi se memorija vrti oko jedne vrijednosti. Tako da tacno vidim da kada uradim dipose da se ista i oslobadja.

Nazalost, treperenje i dalje ostaje, da li suspend/resume bio na pocetku i karju ili bilo kako....
[ vbbojan @ 15.06.2009. 19:18 ] @
Ne mora da se radi za celu formu, mozes i na nivou samog panela.
Evo ti ideja, isto bi trebalo da uradis i kad dodajes kontrole u panel.


Code:


        Dim ctrlprocessed As Integer = 0

        Debug.WriteLine("Broj kontrola u panelu pre ciscenja: " & Me.TableLayoutPanel1.Controls.Count.ToString)

        Dim ctrlArr As ArrayList = New ArrayList(Me.TableLayoutPanel1.Controls)

        'OVDE!
        Me.TableLayoutPanel1.SuspendLayout

        For Each ctrl In ctrlArr

            ctrlprocessed += 1
            ctrl.Dispose()

        Next

        ' I OVDE!
        Me.TableLayoutPanel1.ResumeLayout

        Debug.WriteLine("Broj kontrola kroz koje je prosla petlja: " & ctrlprocessed.ToString)
        Debug.WriteLine("Broj kontrola u panelu posle ciscenja: " & Me.TableLayoutPanel1.Controls.Count.ToString)



[ CallMeSaMaster @ 15.06.2009. 19:34 ] @
@vbbojan

Pokusao sve ali ne pomaze....Razmisljam da zamjenim tu kontrolu ali enmam bas puno izbora...
Stvarno ne kontam zasto se ovo desava...

[ CallMeSaMaster @ 15.06.2009. 19:42 ] @
Ne znam zasto ali sad odjednom radi!
Stavio sam da se tokom dispose() tablelayoutpanel.visible = false
I to je radilo

Sada stavim suspend/resume i isto radi


Hvala vam velika svima na pomoci!