mono / xwt

A cross-platform UI toolkit for creating desktop applications with .NET and Mono
MIT License
1.37k stars 241 forks source link

Endless memoy Increase #304

Open terrak opened 10 years ago

terrak commented 10 years ago

Hello, I make a try with your library and I think I have found a memory management error.

I write a simple program to test the class ImageBuilder and Image for making a tool that run 24h/24 7d/7. The object of this sample is to show triangles which blink (at every 800 ms) and hide or show randomly every (3s, 5s, 10s and 15s) I use Opensuse 12.3 with mono version : Mono JIT compiler version 3.2.3 I use top to show memory usage and i saw that memory increase non-stop !

I think I have add all the dispose need by your library.

I can send you a tar.gz (500k) with this sample.

Here is the code :

MAINWINDOW.CS

using System; using Xwt;

namespace XWT_test { public class MainWindow : Window { public MainWindow () : base() { Build (); }

    #region Build

    private void Build()
    {
        this.Title = "Xwt Demo Dessin";
        this.Width = 1000;
        this.Height = 800 ;
        this.FullScreen = true;

        HPaned hp1 = new HPaned (){ Position=this.Width/2 };
        hp1.Panel1.Content = new DemoDessin ("3sec",60, new TimeSpan(0,0,3));
        hp1.Panel2.Content = new DemoDessin ("5sec",70, new TimeSpan(0,0,5));

        HPaned hp2 = new HPaned (){ Position=this.Width/2 };
        hp2.Panel1.Content = new DemoDessin ("10sec",80, new TimeSpan(0,0,10));
        hp2.Panel2.Content = new DemoDessin ("15sec",90, new TimeSpan(0,0,15));

        VPaned vp = new VPaned () { Position = this.Height/2};
        vp.Panel1.Content = hp1;
        vp.Panel2.Content = hp2;

        this.Content = vp;
    }

    #endregion

    #region Evenements

    protected override bool OnCloseRequested ()
    {
        Application.Exit ();
        return true;
    }

    #endregion
}

}

DEMODESSIN.CS

using System; using System.Collections.Generic; using Xwt; using Xwt.Drawing;

namespace XWT_test { public class DemoDessin : Canvas { Image bufferNormal = null, bufferCli = null;

    public class Triangle 
    {
        public Point A, B, C;
        public Color contour, fond;

        public void Draw (Context ctx, bool cli)
        {
            ctx.SetLineWidth (1.0);
            ctx.SetColor ((cli?fond:contour));
            ctx.MoveTo (A);
            ctx.LineTo (B);
            ctx.LineTo (C);
            ctx.Fill ();
            ctx.MoveTo (A);
            ctx.LineTo (B);
            ctx.LineTo (C);
            ctx.SetColor ((cli?contour:fond));
            ctx.Stroke ();
            ctx.ClosePath ();
        }
    }

    List<Triangle> triangles;
    string nom;
    TimeSpan actualisation;

    public DemoDessin (string nom, int timerRedraw,  TimeSpan actualisation)
    {
        this.nom = nom;
        this.actualisation = actualisation;
        CreateObjects (timerRedraw);
        ActualiseBuffer ();
        this.BackgroundColor = new Color (0.2, 0.2, 0.2);
    }

    protected override void OnDraw (Context ctx, Rectangle dirtyRect)
    {
        Console.WriteLine ("OnDraw " + nom);
        ctx.Save ();
        if ( cliValue )
            ctx.DrawImage (bufferCli, 0, 0);
        else
            ctx.DrawImage (bufferNormal, 0, 0);

        ctx.Restore ();
    }

    public void ActualiseBuffer(){
        Random rand = new Random();

        if (bufferNormal != null)
            bufferNormal.Dispose ();
        if (bufferCli != null)
            bufferCli.Dispose ();

        ImageBuilder 
            ibNormal = new ImageBuilder (1920, 1080),
            ibCli = new ImageBuilder (1920, 1080);

        int count = 0;
        foreach (Triangle t in triangles) {
            if (rand.NextDouble () > 0.3) {
                t.Draw (ibNormal.Context, false);
                t.Draw (ibCli.Context, true);
                count ++;
            }
        }

        Console.WriteLine ("ActualiseBuffer " + nom+ " => "+count+" triangles ");

        bufferNormal = ibNormal.ToBitmap ();
        bufferCli = ibCli.ToBitmap ();

        ibNormal.Context.Dispose ();
        ibCli.Context.Dispose ();
        ibNormal.Dispose ();
        ibCli.Dispose ();
    }

    #region Constructeurs

    private void CreateObjects (int timerMS)
    {
        triangles = new List<Triangle>();
        Random rand = new Random();

        for (int i = 0; i< 2500 ; i++ )
        {
            Point D = new Point( rand.NextDouble()*1920, rand.NextDouble()*1080 );
            double r = rand.NextDouble(), v= rand.NextDouble(), b = rand.NextDouble();
            r = 0.2+r*0.5;
            v = 0.2+v*0.5;
            b = 0.2+b*0.5;

            Triangle t = new Triangle() { 
                A = new Point(D.X+ rand.NextDouble()*25, D.Y+ rand.NextDouble()*25),
                B = new Point(D.X+ rand.NextDouble()*25, D.Y+ rand.NextDouble()*25),
                C = new Point(D.X+ rand.NextDouble()*25, D.Y+ rand.NextDouble()*25),
                fond = new Color(r, v, b),
                contour = new Color( r+0.3, v+0.3, b+0.3)
            };
            triangles.Add(t);
        }

        Application.TimeoutInvoke (timerMS, RedrawTimer);
    }

    DateTime nextActualisation = DateTime.Now;
    bool bChange = true;
    bool bLastCli = true;

    bool RedrawTimer()
    {
        if (nextActualisation < DateTime.Now) {
            ActualiseBuffer ();
            nextActualisation = DateTime.Now.Add(this.actualisation);
            bChange = true;
        }

        bChange |= cliValue != bLastCli;
        bLastCli = cliValue;

        if ( bChange )
            this.QueueDraw ();

        bChange = false;

        return true;
    }

    #endregion

    #region STATIC timer de clignotement commun

    static bool cliValue = true;
    static System.Timers.Timer timerCli;

    static DemoDessin()
    {
        timerCli = new System.Timers.Timer (800);
        timerCli.Elapsed += delegate {
            Console.WriteLine ("TimerCli");
            cliValue = ! cliValue;
        };
        timerCli.Start ();
    }

    #endregion

}

}

XWTDEMO.CS.

using System; using Xwt;

namespace XWT_test { class XwtDemo { [STAThread] static void Main () { Application.Initialize (ToolkitType.Gtk); var mainWindow = new MainWindow (); mainWindow.Show (); Application.Run (); mainWindow.Dispose (); } } }

Therzok commented 10 years ago

It would be better if you gisted the files.

terrak commented 10 years ago

Here a link for the solution in monodevelop : https://sharing.oodrive.com/easyshare/fwd/link=BZcr1HOhQw6l2HDGdvrQgC