Animacja - przemieszczanie na panelu - out of memory

0

Witam,

Piszę program, który robi symulację poruszania się osób po pewnej strefie. Po dokonani obliczeń i symulacji chciałbym zrobic animację.
Mam w kolekcji zrobiony spis kolejnych kroków kazdej osoby i za pomoca Timera wskazuje kolejne pozycje listy. W danej pozycji rysowany jest osoba:

private void Start(object sender, EventArgs e)
        {
            TickZegara = 0;
            Zegar = new Timer();
            Zegar.Interval = (10); 
            Zegar.Tick += new EventHandler(zegar_Tick);
            Zegar.Start();
        }
void zegar_Tick(object sender, EventArgs e)
        {
            promienPickera = 10;
            Pen pioro = new Pen(Color.Black);
            pioro.Width = 1;
            
                tlo = new Bitmap(Obiekty_Static.TłoStrefy);
                g = Graphics.FromImage(tlo);
                this.PanelRysunku.BackgroundImage = tlo;

                for (int i = 0; i < Obiekty_Static.LiczbaPracownikow; i++) //po wszystkich pracownikach
                {
                    SolidBrush KolorPickera = new SolidBrush(Tablice.TablicaPracownicy[i].Kolor);
                    if (KrokAnimacji[i] < Tablice.TablicaPracownicy[i].wspKolejnychKrokowDoAnimacji.Count)
                    {
                        Point lokalizacja = Tablice.TablicaPracownicy[i].wspKolejnychKrokowDoAnimacji[TickZegara];
                        Rysuj(KolorPickera, promienPickera, pioro, lokalizacja);
                        KrokAnimacji[i]+=szybkosc;
                    }
                }
                TickZegara += szybkosc; ;
            }
        private void Rysuj(SolidBrush Kolor, int promienPickera, Pen pioro, Point Lokalizacja)
        {
            g.FillRectangle(Kolor, Lokalizacja.X - promienPickera / 2, Lokalizacja.Y - promienPickera / 2, promienPickera, promienPickera);
            g.DrawRectangle(new Pen(Color.Blue), Lokalizacja.X - promienPickera / 2, Lokalizacja.Y - promienPickera / 2, 				promienPickera, promienPickera);
        }

U mnie na komputerze nie ma problemu, jednak na innym kompie (o dobrych parametrach - np. 4gb ram) wyskakuje mi błąd w trakcie rysowania kolejnych iteracji na panelu. Błąd w linii: Application.Run(new Form1());

static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

w załączeniu zrzut błędu.

Ma może ktoś jakieś sugestie? Czy można jakoś usprawnić kod nie zwiększając interwału timera bo wówczas animacja jest bardzo klatkowa (toporna)? W końcu jest to tylko rysowanie na panelu tyle ze częste. Dodatkowo panel jest ustawiony na doublebuffered.
Będę wdzięczny za wszystkie sugestie...

Pozdrawiam
K.

0

Potraktuj moją podpowiedź eksperymentalnie, bo sam nie jestem pewien. Jesli dobrze widzę ze screenshota, to brak pamięci jest spowodowany obiektem graficznym (Source = System.Drawing). W metodzie zegar_Tick() tworzysz obiekty:
Pen pioro
tlo (Bitmap)
g (Graphics.FromImage())
SolidBrush KolorPickera

wywołaj na nich Dispose() pod koniec metody zegar_Tick(), aby zwolnić ich zasoby. Znalazlem przed chwilą podobne wywołanie dla Graphics w przykładzie tu:
http://msdn.microsoft.com/en-us/library/system.drawing.graphics.fromimage.aspx

0
Tomek2 napisał(a)

Potraktuj moją podpowiedź eksperymentalnie, bo sam nie jestem pewien. Jesli dobrze widzę ze screenshota, to brak pamięci jest spowodowany obiektem graficznym (Source = System.Drawing). W metodzie zegar_Tick() tworzysz obiekty:
Pen pioro
tlo (Bitmap)
g (Graphics.FromImage())
SolidBrush KolorPickera

wywołaj na nich Dispose() pod koniec metody zegar_Tick(), aby zwolnić ich zasoby. Znalazlem przed chwilą podobne wywołanie dla Graphics w przykładzie tu:
http://msdn.microsoft.com/en-us/library/system.drawing.graphics.fromimage.aspx

Tomek2
Dzięki za podpowiedź. To może się udać. Za chwilę wprowadzę zmiany do kodu, a jutro sprawdzę czy coś to pomogło na innym kompie. Bo tak jak pisałem w domu nie pojawia się ten problem. Odezwę się jutro czy coś pomogło...
Dziękuje i pozdrawiam

P.s. Jeżeli ktoś ma jeszcze jakieś inne pomysły to chętnie również wysłucham...

0
Kudłacz napisał(a)
Tomek2 napisał(a)

Potraktuj moją podpowiedź eksperymentalnie, bo sam nie jestem pewien. Jesli dobrze widzę ze screenshota, to brak pamięci jest spowodowany obiektem graficznym (Source = System.Drawing). W metodzie zegar_Tick() tworzysz obiekty:
Pen pioro
tlo (Bitmap)
g (Graphics.FromImage())
SolidBrush KolorPickera

wywołaj na nich Dispose() pod koniec metody zegar_Tick(), aby zwolnić ich zasoby. Znalazlem przed chwilą podobne wywołanie dla Graphics w przykładzie tu:
http://msdn.microsoft.com/en-us/library/system.drawing.graphics.fromimage.aspx

Tomek2
Dzięki za podpowiedź. To może się udać. Za chwilę wprowadzę zmiany do kodu, a jutro sprawdzę czy coś to pomogło na innym kompie. Bo tak jak pisałem w domu nie pojawia się ten problem. Odezwę się jutro czy coś pomogło...
Dziękuje i pozdrawiam

P.s. Jeżeli ktoś ma jeszcze jakieś inne pomysły to chętnie również wysłucham...

Niestety, ale wprowadzona optymalizacja kodu nie przyniosła zamierzonych skutków. ma ktoś może jeszcze jakiś pomysł?
Będę wdzięczny...
K

0

nie zwalniasz g, pioro, tlo, KolorPickers, w zasadzie nie niszczysz kompletnie nic. ja rozumiem, że jest GC, ale wodę w kiblu spuszczasz sam, czy czekasz aż przyjdzie klozetbabcia?
dobrą praktyką jest tworzyć i używać każdy obiekt implementujący interfejs IDisposable w klauzuli using.

a tak z innej bajki - używasz trzech różnych konwencji nazewniczych (camel case, java, podkreślenia), do tego mieszasz angielski z polskim... tak się nie robi. w .net wszystko powinno być po angielsku i w takiej konwencji, jakiej używają biblioteki, czyli camel case (ewentualnie zmienne lokalne i parametry z małej litery).

0

Z odpowiedzi Kudłacza wynika, że dodanie Dispose() nic nie dalo. Ale w sumie mógłby podać jak wygląda kod po zmianach.
Kudlacz - nie wstydź się i pokaż poprawiony kod :) No i czy podobnych operacji rysowania nie ma w innych metodach, gdzie nic nie jest niszczone?

0
Tomek2 napisał(a)

Z odpowiedzi Kudłacza wynika, że dodanie Dispose() nic nie dalo. Ale w sumie mógłby podać jak wygląda kod po zmianach.
Kudlacz - nie wstydź się i pokaż poprawiony kod :) No i czy podobnych operacji rysowania nie ma w innych metodach, gdzie nic nie jest niszczone?

Tomku2,

Już podrzucam kod. Wstydzić się nie wstydzę, choć niejednokrotnie dostałem już od forumowiczów słowną jo*kę :). Nie mniej jednak odbieram to jako konstruktywną krytykę i dużo dzięki niej się uczę. A nie mam żadnych podstaw w programowaniu i zaczynam od nowa pisząc swoją aplikację.

 void zegar_Tick(object sender, EventArgs e)
        {

            promienPickera = 10;
            Pen pioro = new Pen(Color.Black);
            pioro.Width = 1;
            
                Bitmap tlo2 = new Bitmap(Obiekty_Static.TłoStrefy);
                g = Graphics.FromImage(tlo2);
                this.PanelRysunku.BackgroundImage = tlo2;

                for (int i = 0; i < Obiekty_Static.LiczbaPracownikow; i++) //po wszystkich pracownikach
                {
                    SolidBrush KolorPickera = new SolidBrush(Tablice.TablicaPracownicy[i].Kolor);
                    if (KrokAnimacji[i] < Tablice.TablicaPracownicy[i].wspKolejnychKrokowDoAnimacji.Count)
                    {
                        Point lokalizacja = Tablice.TablicaPracownicy[i].wspKolejnychKrokowDoAnimacji[TickZegara];
                        Rysuj(KolorPickera, promienPickera, pioro, lokalizacja, i);
                        KrokAnimacji[i]+=szybkosc;
                    }
                    KolorPickera.Dispose();
                }
                
		TickZegara += szybkosc;
                //tlo2.Dispose();
                pioro.Dispose();
                g.Dispose();
            }

Jeżeli chodzi o tlo2 to nie da się go "zniszczyć".
Co do konwencji nazewniczych to faktycznie jest tu "misz masz" ale tak jak mówiłem brak jakichkolwiek podstaw i doświadczenia usprawiedliwia mam nadzieję brak tego
typu nawyków. Poszperam też w temacie interfejsu IDisposable o którym wspomniał ŁF, bo też go nie znam.
Jeżeli chodzi o brak niszczenia w innych metodach to pewnie bym to znalazł, ale są to pojedyncze przypadki i nie w pętlach. Nie mniej jednak przeszukam kod pod tym względem.
Jeszcze raz dzięki za zainteresowanie tematem i chęci pomocy...
Pozdro

0

Zauważyłem, że w metodzie Rysuj() tworzysz "new Pen(Color.Blue)". Spróbuj na nim też wywołać Dispose().
Wracając do zegar_Tick(): przy każdym jej wywołaniu tworzysz tlo2, ktore jak widzę zawsze jest inicjowane tą samą wartością, a z niego tworzony obiekt "g" typu Graphics. Proponuję stworzyć "g" wcześniej i tylko raz (np. konstruktor klasy Form 1 lub w momencie naciśnięcia "Start") i zniszczyć przy zamykaniu aplikacji (lub przycisku Stop).

W obecnym kodzie (tym po poprawkach) "g" jest zawsze inicjowane od nowa i to tą samą bitmapą - nie wiem jak z tym sobie radzi .NET Framework - czy potrafi poprawnie zwolnić zasoby.

0
Tomek2 napisał(a)

Zauważyłem, że w metodzie Rysuj() tworzysz "new Pen(Color.Blue)". Spróbuj na nim też wywołać Dispose().
Wracając do zegar_Tick(): przy każdym jej wywołaniu tworzysz tlo2, ktore jak widzę zawsze jest inicjowane tą samą wartością, a z niego tworzony obiekt "g" typu Graphics. Proponuję stworzyć "g" wcześniej i tylko raz (np. konstruktor klasy Form 1 lub w momencie naciśnięcia "Start") i zniszczyć przy zamykaniu aplikacji (lub przycisku Stop).

W obecnym kodzie (tym po poprawkach) "g" jest zawsze inicjowane od nowa i to tą samą bitmapą - nie wiem jak z tym sobie radzi .NET Framework - czy potrafi poprawnie zwolnić zasoby.

Tomek2,

Dzięki za kolejne spostrzeżenia. Niestety aktualnie zostałem zmuszony skupić się bardziej na czym innym. Nie mniej jednak, przeanalizuje Twoje propozycję rozwiązania problemu i wprowadzę do kodu. Obiecuję, ze jak będę już coś wiedział to dam znać w tym temacie na forum...
Dzięki
K.

0
Kudłacz napisał(a)
Tomek2 napisał(a)

Zauważyłem, że w metodzie Rysuj() tworzysz "new Pen(Color.Blue)". Spróbuj na nim też wywołać Dispose().
Wracając do zegar_Tick(): przy każdym jej wywołaniu tworzysz tlo2, ktore jak widzę zawsze jest inicjowane tą samą wartością, a z niego tworzony obiekt "g" typu Graphics. Proponuję stworzyć "g" wcześniej i tylko raz (np. konstruktor klasy Form 1 lub w momencie naciśnięcia "Start") i zniszczyć przy zamykaniu aplikacji (lub przycisku Stop).

W obecnym kodzie (tym po poprawkach) "g" jest zawsze inicjowane od nowa i to tą samą bitmapą - nie wiem jak z tym sobie radzi .NET Framework - czy potrafi poprawnie zwolnić zasoby.

Tomek2,

Dzięki za kolejne spostrzeżenia. Niestety aktualnie zostałem zmuszony skupić się bardziej na czym innym. Nie mniej jednak, przeanalizuje Twoje propozycję rozwiązania problemu i wprowadzę do kodu. Obiecuję, ze jak będę już coś wiedział to dam znać w tym temacie na forum...
Dzięki
K.

Witam,

Po pewnym czasie udało mi się powrócić do prac nad aplikacją, więc wracam do tematu. Otóż faktycznie out of memory pojawia się gdyż w metodzie zegar_Tick() tworzony jest za każdym razem nowa Bitmapa. Jeżeli pominie się tą linijkę w tej metodzie a Bitmapę utworzy gdzieś wcześniej problem znika. Jednak wówczas program nie robi tego co powinien. A dokładnie chodzi o to by na PaneluRysunku wyświetlić tlo2 i na nim rysować obiekty (pracowników) za pomocą metody Rysuj(). Następnie po każdym ticknieciu zegara na Panelu pojawia się znów czyste tlo2 i na nim rysuje pracowników w nowych lokalizacjach (pokazując ich przemieszczanie). W momencie gdy w zegar_Tick() nie tworzę nowej bitmapy to z każdym ticknieciem zegara dorysowywani są nowi pracownicy do tła ze starymi pracownikami i robi się wielki bałagan. Ma ktoś pomysł jak to zrobić nie tworząc za każdym razem nowej bitmapy tlo2? Aktualnie metoda wygląda

void zegar_Tick(object sender, EventArgs e)
        {
 
             g = Graphics.FromImage(tlo2);
             this.PanelRysunku.BackgroundImage = tlo2;
                for (int i = 0; i < Obiekty_Static.LiczbaPracownikow; i++) //po wszystkich pracownikach
                {
                    SolidBrush KolorPickera = new SolidBrush(Tablice.TablicaPracownicy[i].Kolor);
                    if (KrokAnimacji[i] < Tablice.TablicaPracownicy[i].wspKolejnychKrokowDoAnimacji.Count)
                    {
                        Point lokalizacja = Tablice.TablicaPracownicy[i].wspKolejnychKrokowDoAnimacji[TickZegara];
                        Rysuj(KolorPickera, promienPickera, pioro, lokalizacja, i);
                        KrokAnimacji[i]+=szybkosc;
                    }
                    this.PanelRysunku.Refresh();
                    KolorPickera.Dispose();
                }

                TickZegara += szybkosc;
                this.PanelRysunku.Refresh();
                pioro.Dispose();
                g.Dispose();
                
        
            }

Nie rozumiem do końca dlaczego tak się dzieje skoro na początku każdego tickniecia zegara robione jest

	g = Graphics.FromImage(tlo2);
             this.PanelRysunku.BackgroundImage = tlo2;

więc teoretycznie g za każdym razem na początku powinno byc czystym tlem2...

Proszę o jakieś sugestie
Pozdrawiam
K.

0

Graphics g służy do malowania po obrazku tlo2, a nie po obiekcie g. już po pierwszej iteracji Twoje tło przestaje być "czyste".
bohatersko walczysz z problemami, które sam stworzyłeś. załącz do posta całe solution (tylko bin i obj daruj), to poprawię i pokażę Ci, jak to powinno wyglądać.

0
ŁF napisał(a)

Graphics g służy do malowania po obrazku tlo2, a nie po obiekcie g. już po pierwszej iteracji Twoje tło przestaje być "czyste".
bohatersko walczysz z problemami, które sam stworzyłeś. załącz do posta całe solution (tylko bin i obj daruj), to poprawię i pokażę Ci, jak to powinno wyglądać.

Wiesz co,

Problem o którym mówię jest częścią większej całości. A jeśli podeślę cały projekt to pewnie cięzko będzie ci sie w nim połapać (oczywiście z powodu przejrzystości kodu). Jak pisałem jestem początkujący i tam tylko pewnie dziada i baby brak :) Zatem może uda Ci się mnie jakoś naprowadzić na rozwiązanie, bo siedzę dumam i nic...

1

piszesz niezgodnie z regułami programistycznego ying-yang i stąd problemy.
po pierwsze - wszystko co nie jest używane do pamiętania stanu obiektu lub buforowania powinieneś umieszczać w zmiennych lokalnych, na przykład to nieszczęsne g.
po drugie - wszystko co tworzysz musisz zniszczyć. w c# sprząta po Tobie gc, ale robi to dopiero jak musi i w dodatku śmieci są śmieciami tylko po zgubieniu wszystkich referencji do nich. dlatego każdy lokalny obiekt klasy implementującej IDisposable powinien być używany w klauzuli using (ewentualnie w klauzuli finally powinno być wywoływane Dispose()). jeśli tak nie jest, a obiekt implementuje metody typu Close(), Dispose() itp, to również powinny być wywołane.
nie panujesz nad swoim kodem, moim zdaniem nie rozumiesz, co się w nim dzieje, patrz mój ostatni post, gdzie stwierdziłem, że nie rozumiesz, po czym malujesz. powinieneś raz załadować obrazek tła do pola obiektu, a w metodzie wywoływanej przez timer powinieneś tworzyć lokalną kopię tego obrazka (Clone()), na lokalnej kopii tworzyć lokalny obiekt Graphics g, a po zakończeniu malowania zniszczyć oba nowe obiekty. SolidBrush KolorPickera nie musi być tworzone wielokrotnie, przecież raz utworzonemu pędzlowi można zmieniać kolor. this.PanelRysunku.BackgroundImage = tlo2; jest bez sensu w Twoim kodzie, skoro zmieniasz g, to zmieniasz tlo2, a PanelRysunku.BackgroundImage to referencja do tlo2, więc to ten sam obiekt, co tlo2 - wiec to przypisanie jest zbędne. rozumiem, że to pozostałości po poprzedniej wersji kodu (która - nota bene - była moim zdaniem lepsza ;-)).
istnieją narzędzia do wykrywania wycieków pamięci, zapoznaj się z jednym z nich. wykomentowując coraz więcej kodu też możesz sprawdzić, który obiekt konkretnie powoduje wyciek.

1
ŁF napisał(a)

piszesz niezgodnie z regułami programistycznego ying-yang i stąd problemy.
po pierwsze - wszystko co nie jest używane do pamiętania stanu obiektu lub buforowania powinieneś umieszczać w zmiennych lokalnych, na przykład to nieszczęsne g.
po drugie - wszystko co tworzysz musisz zniszczyć. w c# sprząta po Tobie gc, ale robi to dopiero jak musi i w dodatku śmieci są śmieciami tylko po zgubieniu wszystkich referencji do nich. dlatego każdy lokalny obiekt klasy implementującej IDisposable powinien być używany w klauzuli using (ewentualnie w klauzuli finally powinno być wywoływane Dispose()). jeśli tak nie jest, a obiekt implementuje metody typu Close(), Dispose() itp, to również powinny być wywołane.
nie panujesz nad swoim kodem, moim zdaniem nie rozumiesz, co się w nim dzieje, patrz mój ostatni post, gdzie stwierdziłem, że nie rozumiesz, po czym malujesz. powinieneś raz załadować obrazek tła do pola obiektu, a w metodzie wywoływanej przez timer powinieneś tworzyć lokalną kopię tego obrazka (Clone()), na lokalnej kopii tworzyć lokalny obiekt Graphics g, a po zakończeniu malowania zniszczyć oba nowe obiekty. SolidBrush KolorPickera nie musi być tworzone wielokrotnie, przecież raz utworzonemu pędzlowi można zmieniać kolor. this.PanelRysunku.BackgroundImage = tlo2; jest bez sensu w Twoim kodzie, skoro zmieniasz g, to zmieniasz tlo2, a PanelRysunku.BackgroundImage to referencja do tlo2, więc to ten sam obiekt, co tlo2 - wiec to przypisanie jest zbędne. rozumiem, że to pozostałości po poprzedniej wersji kodu (która - nota bene - była moim zdaniem lepsza ;-)).
istnieją narzędzia do wykrywania wycieków pamięci, zapoznaj się z jednym z nich. wykomentowując coraz więcej kodu też możesz sprawdzić, który obiekt konkretnie powoduje wyciek.

ŁF-ie,

Dziękuję za posta i poradę. Zgadzam się całkowicie z Twoimi "zarzutami" pod kątem moich umiejętności programowania i rozumienia kodu. Nie mniej jednak nie masz pojęcia ile dają takie posty napisane przez forumowiczów. Uczą więcej niż nie jedna książka i zwracają uwagę na błędy popełniane przez młodych pseudo-programistów.
Póki co tak na szybko wykorzystałem Twoje rady dot. wykorzystanie Clone() i uzyskałem oczekiwane efekty. Nie zdążyłem jeszcze uporządkować kodu i wprawadzić wszystkich poprawek dot. niszczenia obiektów itp. Ale zamieszczam poniżej.

        void zegar_Tick(object sender, EventArgs e)
        {

            Rectangle obszar = new Rectangle(0, 0, tloStale.Width, tloStale.Height);
            System.Drawing.Imaging.PixelFormat format = tloStale.PixelFormat;
            Image tlozmienne = tloStale.Clone(obszar, format);
            Graphics Rysunek = Graphics.FromImage(tlozmienne);

            for (int i = 0; i < Obiekty_Static.LiczbaPracownikow; i++) //po wszystkich pracownikach
            {
                SolidBrush KolorPickera = new SolidBrush(Tablice.TablicaPracownicy[i].Kolor);
                if (KrokAnimacji[i] < Tablice.TablicaPracownicy[i].wspKolejnychKrokowDoAnimacji.Count)
                {
                    Point lokalizacja = Tablice.TablicaPracownicy[i].wspKolejnychKrokowDoAnimacji[TickZegara];
                    Rysuj(KolorPickera, promienPickera, pioro, lokalizacja, i, Rysunek);
                    KrokAnimacji[i] += szybkosc;
                }

                KolorPickera.Dispose();
            }
            TickZegara += szybkosc;
            this.PanelRysunku.BackgroundImage = tlozmienne;
            pioro.Dispose();
            Rysunek.Dispose();
        }
        private void Rysuj(SolidBrush Kolor, int promienPickera, Pen pioro, Point Lokalizacja, int nrpickera, Graphics rysunek)
        {
            rysunek.FillRectangle(Kolor = new SolidBrush(Color.Transparent), Lokalizacja.X - promienPickera / 2, Lokalizacja.Y - promienPickera / 2, promienPickera, promienPickera);
            rysunek.DrawRectangle(new Pen(Color.Blue), Lokalizacja.X - promienPickera / 2, Lokalizacja.Y - promienPickera / 2, promienPickera, promienPickera);
            String Tekst = (nrpickera+1).ToString();
            Font Czcionka = new Font("Arial", 6);
            SolidBrush drawBrush = new SolidBrush(Color.Black);
            StringFormat drawFormat = new StringFormat();
            drawFormat.FormatFlags = StringFormatFlags.DirectionRightToLeft;
            drawFormat.Alignment = StringAlignment.Center;
            rysunek.DrawString(Tekst, Czcionka, drawBrush, Lokalizacja.X - promienPickera / 2, Lokalizacja.Y - promienPickera / 2);
            Czcionka.Dispose();
            Kolor.Dispose();
        }

wieczorem pozbędę się niepotrzebnie tworzonych lokalnie obiektów.
Jeszcze raz dziękuję za pomoc i zwrócenie uwagi na ogólne nieprawidłowości w pisaniu kodu. Dużo to uczy człowieka...:)
Pozdrawiam
Kudłacz

0

po drugie - wszystko co tworzysz musisz zniszczyć. w c# sprząta po Tobie gc, ale robi to dopiero jak musi i w dodatku śmieci są śmieciami tylko po zgubieniu wszystkich referencji do nich
przy czym problemem tu nie jest zwykle pamięć (bo tą zarządza GC i robi to dobrze) a inne zasoby: otwarte i wiszące połączenia sieciowe, bazodanowe, otwarte pliki (uchwyty systemowe, bufory dyskowe), i inne skomplikowane struktury którymi nie zarządza Framework, więc gc nie ma na nie wpływu.
Otwarty obiekt graphics może (w teorii, bo nie wiem jak to jest zaimplementowane) trzymać dodatkowe bufory dla double- i triple-buffering, może jako tekstura w pamięci karty, i może też dodatkowo obciążać sterowniki karty graficznej (jakieś uchwyty itp.).

Sama alokacja pamięci (operator new) w C# jest nadzwyczajnie szybka — ale pamięć to nie jedyne co obiekty mogą zabierać.

0
Azarien napisał(a)

po drugie - wszystko co tworzysz musisz zniszczyć. w c# sprząta po Tobie gc, ale robi to dopiero jak musi i w dodatku śmieci są śmieciami tylko po zgubieniu wszystkich referencji do nich
przy czym problemem tu nie jest zwykle pamięć (bo tą zarządza GC i robi to dobrze) a inne zasoby: otwarte i wiszące połączenia sieciowe, bazodanowe, otwarte pliki (uchwyty systemowe, bufory dyskowe), i inne skomplikowane struktury którymi nie zarządza Framework, więc gc nie ma na nie wpływu.
Otwarty obiekt graphics może (w teorii, bo nie wiem jak to jest zaimplementowane) trzymać dodatkowe bufory dla double- i triple-buffering, może jako tekstura w pamięci karty, i może też dodatkowo obciążać sterowniki karty graficznej (jakieś uchwyty itp.).

Sama alokacja pamięci (operator new) w C# jest nadzwyczajnie szybka — ale pamięć to nie jedyne co obiekty mogą zabierać.

Azaerin,

Pewnie nie wiem do konca o czym mówisz bo to już inny poziom wtajemniczenia, ale aż sprawdzę czy zamykam połączenie z plikami excela i dodatkowo mam ustawiony doublebuffer dla panelu na którym rysuje...
pzdr

0

A spróbuj umieścić zmienne z funkcji timer'a na zewnątrz i co się wtedy stanie. Tak tylko na razie.

0
xeo545x39 napisał(a)

A spróbuj umieścić zmienne z funkcji timer'a na zewnątrz i co się wtedy stanie. Tak tylko na razie.

Zmienne w funkcji timer'a to zmienne metody void zegar_Tick(object sender, EventArgs e) ?

Czyli chodzi ci o wywalenie poza nią:

                Image CloneTlo = tlo2.Clone(CloneObszar, Cloneformat);
                Graphics gLokalne = Graphics.FromImage(CloneTlo);

????

Jeżeli tak to się to chyba nie uda. Co Tick animacja ma się rysować na czystym tle CloneTlo kopiowanym z tlo2.
Jeżeli wyrzucę to poza metodę to nie będzie się tak działo :(

1 użytkowników online, w tym zalogowanych: 0, gości: 1