Prog.Hu

C# Memoria gondok.
50

2013-09-06T04:34+01:00
sediqwe1
sediqwe1Prog.Hu
regisztrált tag
Sziasztok!
Van egy programom, C# ben, Winform, megnyitogat x oldalt, kilvas belőle y linkeket, és az y linkeket egy datagridbe pakolja, ezt a datagridet egy timer megnyitogatja időnként. Nos, 3-400 link megnyitása után elfogy a ram, és kifagy a program.
Itt valami nagyon nem jól lett megírva.
De mi?
A kiherélt kód:


System.Timers.Timer aTimer = new System.Timers.Timer();
        System.Timers.Timer kijelzo = new System.Timers.Timer();
        private System.Threading.Thread thread;
        private System.Threading.Thread autothread;
 aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

// Elindító gomb megnyomása!
private void button5_Click(object sender, EventArgs e)
        {
            if( dataGridView1.RowCount >0)
            {
            megkeres(10);
            kijelzo.Interval = 1000;
            kijelzo.Enabled = true;
        }}
// Megkeres(10) meghívása (a "10" a teszthez kellett)
//kijelző elindítása (számol + progressbart növel)

 public void megkeres(int mennyi)
        {
                     
                     aTimer.Interval = (Properties.Settings.Default.window * 1000);
                     aTimer.Enabled = true;
                     
                     
        }
// elinditja az aTimer-t ;
private void OnTimedEvent(object source, ElapsedEventArgs e )
        {
           
            this.BeginInvoke((MethodInvoker)delegate
            {
                    progressBar1.Value = 0;
               
            });
            k = k + 1;
           
            if (dataGridView1.RowCount <= 0)
            {
                aTimer.Stop();
                kijelzo.Stop();
            }
               
            else
            {
                if (thread != null)
                {
                    thread.Abort();
                }         
                            thread = new System.Threading.Thread(megnyit);
                            thread.Start();
                            Console.WriteLine("Egyik szál elindult: " + k);
           
         }

        }
// ellenörzi hogy fut e már egy ilyen thread, ha igen, leállítja, ellenörzi hogy van e feldolgozandó cucc a listában

 public void megnyit()
        {
            if (dataGridView1.RowCount > 0)
            {
                string link = dataGridView1.Rows[0].Cells[2].Value.ToString().Trim();
               lement(link);
               
                var methodInvoker = new MethodInvoker(() =>
                {
                    webKitBrowser2.Navigate(link);
                    dataGridView1.Rows.Remove(dataGridView1.Rows[0]);
                   
                });

                Invoke(methodInvoker);
            }
            felszamit();
               
        }
//beolvassa az datagrid 2. cellájában lévő linket a Linkbe elnavigálja a WebKitBrowser-t a linkre, eltávolítja a megnyitott linket a datagridviewből és lementi hogy többé ne legyen beolvasva ...
private void lement(string link)
        {
            sqldolgozo.execute("insert into cimek (link) values('" + link + "')", "collect");
        }
public void felszamit()
        {
                    var methodInvoker2 = new MethodInvoker(() =>
                    {
            label1.Text = "Listában: " + dataGridView1.RowCount.ToString();
                    });
          BeginInvoke(methodInvoker2);
         
                    }
Nos ha jóllátom akkor kb ennyi fele megy a program.
De itt valahol nagyon durván túl töltöm a ramot :( egyszerüen nem jöttem rá miért nem gyilkol rendesen a GC!! 800 megánál kifagyott a program :(

elnézést a nagy és átláthatatlan kódért...
Mutasd a teljes hozzászólást!
C# Memoria gondok.
2013-09-06T04:34+01:00
sediqwe1
sediqwe1Prog.Hu
regisztrált tag
Oké, de azóta vannak újabb fejlemények. Olvasd már végig a topicot, légyszi!
Mutasd a teljes hozzászólást!
Mint látod, 4 perc hijján egyszerre irtunk , amikor leírtad a memoria leak-t, én meg írtam hogy csak most tudok vele foglalkozni, igyekeztem a héten olvasgatni, most az amit pont egyszerre irtunk, még nem lett áttanulmányozva, so sorry :)
semmit nem hagyok ki, most van időm , tesztelem amit irtál, olvasgatom a linkeket, tesztelem a bgw -t stb stb :) nem hajt a tatár, nekem IS fontos hogy megoldódjon a gond! A segítséged is fontos! csak na :) hétvégén van időm programozni :)
Mutasd a teljes hozzászólást!
Erről tudsz nekem nyilatkozni hogy ez mi is?
Mert ez viszont püpecül nem engedte zabálni a ramot!
eddig 4x mega a max és kitakarítja 5 megáig a lapváltáskor a program ramigényét! De hogy és mi müködik???
Válaszod előre is köszönöm!
a workaround a következő amit átnézek! Illetve a programom most "selejteztem" ki, és kezdem elölről , legalábbis a müködtető részét.
Mutasd a teljes hozzászólást!
Hát ez az! Az MSDN-en Microsoft-osok is ezt javasolják, holott ez a SetProcessWorkingSetSize funkció nem memóriát takarít, hanem csak kényszeríti az aktuális process-t, hogy írjon ki mindent a pagefile-ba, amit csak lehet, azaz hogy a fizikai memóriát szabadítsa fel.

Ebből az következik, hogy a szivárgás elvileg megmarad, bizony előbb-utóbb ugyanúgy be fog telni a memória, ugyanakkor nálam úgy tűnt, mégis működik (a teljes memóriafoglalás állandó maradt). Kérdés, hogy mennyi ideig kell, hogy működjön a programod újraindítás nélkül. Ha esetleg hetekig, akkor félő, hogy ez nem lesz végleges megoldás. Igazából hagynod kéne futni annyi ideig, amennyire szükséged van.

Még egy fontos aspektus: mint látod, ez nem .NET funkció, hanem WIN32 API hívás, így nem garantálható, hogy minden .NET környezetben, minden platformon működni fog. Elvileg Windows XP-től felfelé működik.

a workaround a következő amit átnézek


Ez a workaround.

Illetve a programom most "selejteztem" ki, és kezdem elölről , legalábbis a müködtető részét.


Amennyiben ez megbízhatóan működik (legalábbis olyan időtartamig, ami neked elegendő), akkor érdemes csak továbblépni. Én javaslom, hogy az itt leírt programszerkezetet használd, mindenképpen kerüld a thread indítgatást/leállítást timer-ből!
Mutasd a teljes hozzászólást!
Szivem szerint már az XPt se támogatnám, (a webes énem és a ie6.0 gyülölete miatt is) de ez winform.net így nem "kényszeríthetem" a usert, főleg nem ilyen loser kis program miatt hogy cseréljen oprendszert :)
így XP -> SP2 / Vista / Win8 a terv, lejjebb semmiképpen nem akarom engedni a progit (.net4 a követelmény ugyebár :) )
Most egyelőre gyerek sétáltatás, közben a laptop futtatja normális linkekkel a programot, és nézem a win7 változásait is, hogy mi nő, csökken, mennyi szál fut, és a crash eket is lesem (most jelenleg tele firkálja a progi exception okkal a MSV-t!
Majd még jelentkezem , ma :)
Mutasd a teljes hozzászólást!
Mivel teszteltem a metódust, és ez önmagában "megoldás" a hibára, most jelenleg az átalakított módszert lesem. Lehet hogy nem is ott van/ volt a hiba, ezt kicsit' sok idő kideríteni, jelenleg fut a mókus kerék, 43*15*5 másodperc mire kiderül.
kb 20 megnyitás után úgy néz ki hogy bizony nő folyamatosan a memória evészet, bár lényegesen kevésbé.
Szóval valószínüleg(tuti) nem a wb meghívás eszi a memóriámat :\
így már' csak 200 lehetőségem maradt :\
Mivel a megnyitás így zajlik most:
sql adatbázis -> van e adat
sql adatbázis -> bekérem az adatokat
adat (link) megnyitása -> behívás webkitbrowserbe
webkitbrowser.text átnyálazása -> link keresés
linkek berakása -> dataGridViewbe
a linkhez tartozó kép megkeresése -> resource / letöltés webből.
berakás datagridview be.
a memória egyébként csökken folyamatosan, felmegy 130 ra, és onnan 112 nél jár jelenleg, nekem tetszik ez a memória igény, tovább tesztelem.
Áttértem a timer -> true -> tick -> webkitbrowser hívás -> false ha végzett.
Köszönöm a nem kis segítséget!

Mutasd a teljes hozzászólást!
Nagyon szívesen, azonban programozási mintának továbbra is a végtelen ciklusban futó háttérprocess-t javasolnám, mivel timer használatával potenciális hibalehetőségeket generálsz.

Pl.: ha a timer úgy indítja el a feldolgozást, hogy az előző még nem végzett. Ilyen hiba csak ritkán fog előjönni, aztán vadászhatod.

Na mindegy, örülök, hogy sikerült előbbre jutni.
Mutasd a teljes hozzászólást!
Mint látod, még most is fent vagyok és tesztelem.
a ciklust örökké nem szeretném futtatni, inkább felhasználóhoz kötném hogy mikor megy körbe , hiszen sávszélesség függő.
Egyébként addig hegesztettem amig 55mb ról csak 80-ra emelkedett a memória evészet, 43 megnyitással, illetve 26 kép letöltésével.
a megoldáshoz az is hozzá tartozik hogy kivettem a ciklusokból a deklarációkat , mert olvastam valahol hogy nem rá, hanem ujra generálja a változókat, de a régit is meghagyja, szal kitettem a deklarálást a program elejére. így lement majd 100 megát!
tovább szürtem a ciklus indítási paramétereit, így kevesebbszer kell elindulnia, illetve kevesebbszer fut lukra.
kivettem a console.writeline okat mert teszt üzemmódban az is megdobta a memória evést :) már csak' a program másik felét kell, holnap , újra írnoM :))) Bye!
Mutasd a teljes hozzászólást!