Windows Vista Forums

Disposable Canvas?

  1. #1


    Jon Davis Guest

    Disposable Canvas?

    OK, why is Canvas not IDisposable, and how do I get rid of all the Windows
    handles?

    I'm doing a performance test of looping through a dynamic XAML-to-JPEG
    conversion. It gets to about 500 conversions and then crashes. Task Manager
    says that about 6000 Windows handles were created and the count never
    decrements.

    My code (loop not shown):



    protected System.IO.Stream GenImageStream()
    {
    System.IO.Stream retImageStream = null;
    System.IO.StreamReader sr = new
    System.IO.StreamReader("Window1.xaml");
    string xaml = sr.ReadToEnd();
    if (text != null)
    {
    xaml = xaml.Replace("{$TEXT$}", text
    }
    else
    {
    xaml = xaml.Replace("{$TEXT$}", "Enter text.");
    }
    sr.Close();
    System.IO.MemoryStream ms = new
    System.IO.MemoryStream(xaml.Length);
    System.IO.StreamWriter sw = new System.IO.StreamWriter(ms);
    sw.Write(xaml);
    sw.Flush();
    ms.Seek(0, System.IO.SeekOrigin.Begin);
    System.Windows.Controls.Canvas canvas =
    (System.Windows.Controls.Canvas)
    System.Windows.Markup.XamlReader.Load(ms);
    canvas.Background = System.Windows.Media.Brushes.Yellow;
    canvas.Measure(new System.Windows.Size(640d, 480d));
    canvas.Arrange(new System.Windows.Rect(0d, 0d, 640d, 480d));
    System.Windows.Media.Imaging.RenderTargetBitmap rtb
    = new System.Windows.Media.Imaging.RenderTargetBitmap(
    640, 480, 96d, 96d,
    System.Windows.Media.PixelFormats.Default);
    rtb.Render(canvas);
    System.Windows.Media.Imaging.JpegBitmapEncoder encoder
    = new System.Windows.Media.Imaging.JpegBitmapEncoder();
    encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(rtb));
    string fp = Request.PhysicalApplicationPath + "imgtmp\\"
    + (Guid.NewGuid()).ToString() + ".jpg";
    retImageStream = new System.IO.MemoryStream();
    encoder.Save(retImageStream);
    retImageStream.Seek(0, System.IO.SeekOrigin.Begin);
    ms.Dispose();
    }

    Jon


      My System SpecsSystem Spec

  2. #2


    Oliver Sturm [MVP C#] Guest

    Re: Disposable Canvas?

    Hi,

    Jon Davis wrote:

    > OK, why is Canvas not IDisposable, and how do I get rid of all the Windows
    > handles?


    I used a variation of your code to try this myself, but I was unable to
    reproduce the crash behaviour your were referring to. I also used a
    profiler to look out for resource leaks and I didn't find any of these
    either. Here's the code I used:

    private void OnButtonClick( object sender, RoutedEventArgs e) {
    for (int i = 0; i < 1000; i++)
    GenImageStream();
    }


    private static string GetXaml( ) {
    StreamReader sr = new StreamReader("Canvas.xaml");
    string xaml = sr.ReadToEnd( );
    sr.Close( );
    return xaml;
    }

    protected void GenImageStream( ) {
    string xaml = GetXaml( );

    using (MemoryStream ms = new MemoryStream(xaml.Length)) {
    StreamWriter sw = new StreamWriter(ms);
    sw.Write(xaml);
    sw.Flush( );
    ms.Seek(0, SeekOrigin.Begin);

    Canvas canvas = (Canvas) XamlReader.Load(ms);
    canvas.Background = Brushes.Yellow;
    canvas.Measure(new Size(640d, 480d));
    canvas.Arrange(new Rect(0d, 0d, 640d, 480d));
    RenderTargetBitmap rtb = new RenderTargetBitmap(
    640, 480, 96d, 96d, PixelFormats.Default);
    rtb.Render(canvas);
    JpegBitmapEncoder encoder = new JpegBitmapEncoder( );
    encoder.Frames.Add(BitmapFrame.Create(rtb));
    using (Stream outstream = new MemoryStream( ))
    encoder.Save(outstream);
    }
    }


    Oliver Sturm
    --
    http://www.sturmnet.org/blog - MVP C#

      My System SpecsSystem Spec

  3. #3


    Jon Davis Guest

    Re: Disposable Canvas?


    "Oliver Sturm [MVP C#]" <oliver@sturmnet.org> wrote in message
    news:1of44e3mq4rq0$.dlg@sturmnet.org...
    > Hi,
    >
    > Jon Davis wrote:
    >
    >> OK, why is Canvas not IDisposable, and how do I get rid of all the
    >> Windows
    >> handles?

    >
    > I used a variation of your code to try this myself, but I was unable to
    > reproduce the crash behaviour your were referring to.


    That's interesting. It might help if I mention I'm trying to do this on an
    ASP.NET web page to see about the feasibility of dynamically-generating
    images from XAML mark-up, on a heavily impacted web site. The output of
    this is great and seems to be fast, it's just that it crashes after 500
    times and IIS's process has 6000 Windows handles. I'm executing on Windows
    Vista / IIS 7. Here's the full source. I'll take a look at yours as well,
    but in the mean time ... maybe you can spot something really, really stupid
    I'm doing?

    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;

    namespace ImageGenServer
    {
    public partial class GenImage : System.Web.UI.Page
    {
    private System.IO.Stream retImageStream;
    protected void Page_Load(object sender, EventArgs e)
    {
    Gimme();
    }

    protected void Gimme()
    {
    System.Threading.Thread thread = new System.Threading.Thread(
    GimmeMore);
    thread.SetApartmentState(System.Threading.ApartmentState.STA);
    thread.Start();
    while (thread.IsAlive)
    {
    System.Threading.Thread.Sleep(0);
    }
    Response.ContentType = "image/jpeg";
    System.IO.BinaryReader br = new
    System.IO.BinaryReader(retImageStream);
    Response.BinaryWrite(br.ReadBytes((int)retImageStream.Length));
    br.Close();
    retImageStream.Close();
    Response.Flush();

    thread = null;
    br = null;
    retImageStream = null;

    Response.End();
    }

    protected void GimmeMore()
    {
    System.IO.StreamReader sr = new
    System.IO.StreamReader(Request.PhysicalApplicationPath + "Window1.xaml");
    string xaml = sr.ReadToEnd();
    if (Request["text"] != null)
    {
    xaml = xaml.Replace("{$TEXT$}", Request["text"]);
    }
    else
    {
    xaml = xaml.Replace("{$TEXT$}", "Add &quot;text=...&quot; to
    querystring.");
    }
    sr.Close();
    System.IO.MemoryStream ms = new
    System.IO.MemoryStream(xaml.Length);
    System.IO.StreamWriter sw = new System.IO.StreamWriter(ms);
    sw.Write(xaml);
    sw.Flush();
    ms.Seek(0, System.IO.SeekOrigin.Begin);
    System.Windows.Controls.Canvas canvas =
    (System.Windows.Controls.Canvas)
    System.Windows.Markup.XamlReader.Load(
    ms);
    canvas.Background = System.Windows.Media.Brushes.Yellow;
    canvas.Measure(new System.Windows.Size(640d, 480d));
    canvas.Arrange(new System.Windows.Rect(0d, 0d, 640d, 480d));
    System.Windows.Media.Imaging.RenderTargetBitmap rtb
    = new System.Windows.Media.Imaging.RenderTargetBitmap(
    640, 480, 96d, 96d,
    System.Windows.Media.PixelFormats.Default);
    rtb.Render(canvas);
    System.Windows.Media.Imaging.JpegBitmapEncoder encoder
    = new System.Windows.Media.Imaging.JpegBitmapEncoder();
    encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(
    rtb));
    string fp = Request.PhysicalApplicationPath + "imgtmp\\"
    + (Guid.NewGuid()).ToString() + ".jpg";
    retImageStream = new System.IO.MemoryStream();
    encoder.Save(retImageStream);
    retImageStream.Seek(0, System.IO.SeekOrigin.Begin);
    ms.Dispose();

    }
    }
    }



      My System SpecsSystem Spec

  4. #4


    Jon Davis Guest

    Re: Disposable Canvas?

    Died with you code, too. I think this has to do with STA threading. Not sure
    if there is such a thing as a "best practice" for STA threading on ASP.NET.

    Jon


    "Jon Davis" <jon@REMOVE.ME.PLEASE.jondavis.net> wrote in message
    news:exbDR9mjHHA.1776@TK2MSFTNGP05.phx.gbl...
    >
    > "Oliver Sturm [MVP C#]" <oliver@sturmnet.org> wrote in message
    > news:1of44e3mq4rq0$.dlg@sturmnet.org...
    >> Hi,
    >>
    >> Jon Davis wrote:
    >>
    >>> OK, why is Canvas not IDisposable, and how do I get rid of all the
    >>> Windows
    >>> handles?

    >>
    >> I used a variation of your code to try this myself, but I was unable to
    >> reproduce the crash behaviour your were referring to.

    >
    > That's interesting. It might help if I mention I'm trying to do this on an
    > ASP.NET web page to see about the feasibility of dynamically-generating
    > images from XAML mark-up, on a heavily impacted web site. The output of
    > this is great and seems to be fast, it's just that it crashes after 500
    > times and IIS's process has 6000 Windows handles. I'm executing on Windows
    > Vista / IIS 7. Here's the full source. I'll take a look at yours as well,
    > but in the mean time ... maybe you can spot something really, really
    > stupid I'm doing?
    >
    > using System;
    > using System.Data;
    > using System.Configuration;
    > using System.Collections;
    > using System.Web;
    > using System.Web.Security;
    > using System.Web.UI;
    > using System.Web.UI.WebControls;
    > using System.Web.UI.WebControls.WebParts;
    > using System.Web.UI.HtmlControls;
    >
    > namespace ImageGenServer
    > {
    > public partial class GenImage : System.Web.UI.Page
    > {
    > private System.IO.Stream retImageStream;
    > protected void Page_Load(object sender, EventArgs e)
    > {
    > Gimme();
    > }
    >
    > protected void Gimme()
    > {
    > System.Threading.Thread thread = new System.Threading.Thread(
    > GimmeMore);
    > thread.SetApartmentState(System.Threading.ApartmentState.STA);
    > thread.Start();
    > while (thread.IsAlive)
    > {
    > System.Threading.Thread.Sleep(0);
    > }
    > Response.ContentType = "image/jpeg";
    > System.IO.BinaryReader br = new
    > System.IO.BinaryReader(retImageStream);
    > Response.BinaryWrite(br.ReadBytes((int)retImageStream.Length));
    > br.Close();
    > retImageStream.Close();
    > Response.Flush();
    >
    > thread = null;
    > br = null;
    > retImageStream = null;
    >
    > Response.End();
    > }
    >
    > protected void GimmeMore()
    > {
    > System.IO.StreamReader sr = new
    > System.IO.StreamReader(Request.PhysicalApplicationPath + "Window1.xaml");
    > string xaml = sr.ReadToEnd();
    > if (Request["text"] != null)
    > {
    > xaml = xaml.Replace("{$TEXT$}", Request["text"]);
    > }
    > else
    > {
    > xaml = xaml.Replace("{$TEXT$}", "Add &quot;text=...&quot;
    > to querystring.");
    > }
    > sr.Close();
    > System.IO.MemoryStream ms = new
    > System.IO.MemoryStream(xaml.Length);
    > System.IO.StreamWriter sw = new System.IO.StreamWriter(ms);
    > sw.Write(xaml);
    > sw.Flush();
    > ms.Seek(0, System.IO.SeekOrigin.Begin);
    > System.Windows.Controls.Canvas canvas =
    > (System.Windows.Controls.Canvas)
    > System.Windows.Markup.XamlReader.Load(
    > ms);
    > canvas.Background = System.Windows.Media.Brushes.Yellow;
    > canvas.Measure(new System.Windows.Size(640d, 480d));
    > canvas.Arrange(new System.Windows.Rect(0d, 0d, 640d, 480d));
    > System.Windows.Media.Imaging.RenderTargetBitmap rtb
    > = new System.Windows.Media.Imaging.RenderTargetBitmap(
    > 640, 480, 96d, 96d,
    > System.Windows.Media.PixelFormats.Default);
    > rtb.Render(canvas);
    > System.Windows.Media.Imaging.JpegBitmapEncoder encoder
    > = new System.Windows.Media.Imaging.JpegBitmapEncoder();
    >
    > encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(
    > rtb));
    > string fp = Request.PhysicalApplicationPath + "imgtmp\\"
    > + (Guid.NewGuid()).ToString() + ".jpg";
    > retImageStream = new System.IO.MemoryStream();
    > encoder.Save(retImageStream);
    > retImageStream.Seek(0, System.IO.SeekOrigin.Begin);
    > ms.Dispose();
    >
    > }
    > }
    > }
    >




      My System SpecsSystem Spec

  5. #5


    Jon Davis Guest

    Re: Disposable Canvas?

    Setting AspCompat="true" to the .aspx header to make the page STA threaded,
    and dropping the spawning of a new thread, seemed to alleviate this
    significantly. I executed 5000 times before I just killed the test (was
    running low on drive space -- made that many images). Memory consumption by
    the VS debugger web server did go up to 178MB and more than 1000 handles and
    didn't go down after I stopped the test, so there's still a bad memory leak,
    but not anything like before.

    Interesting. However, now I get an error message in Visual Studio when I go
    to debug:

    Error connecting to undo manager of source file 'C:\Documents and
    Settings\jdavis\My Documents\Visual Studio
    2005\Projects\ImageGenServer\ThreadMode.aspx.designer.cs'.


    Jon


    "Jon Davis" <jon@REMOVE.ME.PLEASE.jondavis.net> wrote in message
    news:%23JwprXnjHHA.208@TK2MSFTNGP05.phx.gbl...
    > Died with you code, too. I think this has to do with STA threading. Not
    > sure if there is such a thing as a "best practice" for STA threading on
    > ASP.NET.
    >
    > Jon
    >
    >
    > "Jon Davis" <jon@REMOVE.ME.PLEASE.jondavis.net> wrote in message
    > news:exbDR9mjHHA.1776@TK2MSFTNGP05.phx.gbl...
    >>
    >> "Oliver Sturm [MVP C#]" <oliver@sturmnet.org> wrote in message
    >> news:1of44e3mq4rq0$.dlg@sturmnet.org...
    >>> Hi,
    >>>
    >>> Jon Davis wrote:
    >>>
    >>>> OK, why is Canvas not IDisposable, and how do I get rid of all the
    >>>> Windows
    >>>> handles?
    >>>
    >>> I used a variation of your code to try this myself, but I was unable to
    >>> reproduce the crash behaviour your were referring to.

    >>
    >> That's interesting. It might help if I mention I'm trying to do this on
    >> an ASP.NET web page to see about the feasibility of
    >> dynamically-generating images from XAML mark-up, on a heavily impacted
    >> web site. The output of this is great and seems to be fast, it's just
    >> that it crashes after 500 times and IIS's process has 6000 Windows
    >> handles. I'm executing on Windows Vista / IIS 7. Here's the full source.
    >> I'll take a look at yours as well, but in the mean time ... maybe you can
    >> spot something really, really stupid I'm doing?
    >>
    >> using System;
    >> using System.Data;
    >> using System.Configuration;
    >> using System.Collections;
    >> using System.Web;
    >> using System.Web.Security;
    >> using System.Web.UI;
    >> using System.Web.UI.WebControls;
    >> using System.Web.UI.WebControls.WebParts;
    >> using System.Web.UI.HtmlControls;
    >>
    >> namespace ImageGenServer
    >> {
    >> public partial class GenImage : System.Web.UI.Page
    >> {
    >> private System.IO.Stream retImageStream;
    >> protected void Page_Load(object sender, EventArgs e)
    >> {
    >> Gimme();
    >> }
    >>
    >> protected void Gimme()
    >> {
    >> System.Threading.Thread thread = new System.Threading.Thread(
    >> GimmeMore);
    >> thread.SetApartmentState(System.Threading.ApartmentState.STA);
    >> thread.Start();
    >> while (thread.IsAlive)
    >> {
    >> System.Threading.Thread.Sleep(0);
    >> }
    >> Response.ContentType = "image/jpeg";
    >> System.IO.BinaryReader br = new
    >> System.IO.BinaryReader(retImageStream);
    >>
    >> Response.BinaryWrite(br.ReadBytes((int)retImageStream.Length));
    >> br.Close();
    >> retImageStream.Close();
    >> Response.Flush();
    >>
    >> thread = null;
    >> br = null;
    >> retImageStream = null;
    >>
    >> Response.End();
    >> }
    >>
    >> protected void GimmeMore()
    >> {
    >> System.IO.StreamReader sr = new
    >> System.IO.StreamReader(Request.PhysicalApplicationPath + "Window1.xaml");
    >> string xaml = sr.ReadToEnd();
    >> if (Request["text"] != null)
    >> {
    >> xaml = xaml.Replace("{$TEXT$}", Request["text"]);
    >> }
    >> else
    >> {
    >> xaml = xaml.Replace("{$TEXT$}", "Add &quot;text=...&quot;
    >> to querystring.");
    >> }
    >> sr.Close();
    >> System.IO.MemoryStream ms = new
    >> System.IO.MemoryStream(xaml.Length);
    >> System.IO.StreamWriter sw = new System.IO.StreamWriter(ms);
    >> sw.Write(xaml);
    >> sw.Flush();
    >> ms.Seek(0, System.IO.SeekOrigin.Begin);
    >> System.Windows.Controls.Canvas canvas =
    >> (System.Windows.Controls.Canvas)
    >> System.Windows.Markup.XamlReader.Load(
    >> ms);
    >> canvas.Background = System.Windows.Media.Brushes.Yellow;
    >> canvas.Measure(new System.Windows.Size(640d, 480d));
    >> canvas.Arrange(new System.Windows.Rect(0d, 0d, 640d, 480d));
    >> System.Windows.Media.Imaging.RenderTargetBitmap rtb
    >> = new System.Windows.Media.Imaging.RenderTargetBitmap(
    >> 640, 480, 96d, 96d,
    >> System.Windows.Media.PixelFormats.Default);
    >> rtb.Render(canvas);
    >> System.Windows.Media.Imaging.JpegBitmapEncoder encoder
    >> = new System.Windows.Media.Imaging.JpegBitmapEncoder();
    >>
    >> encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(
    >> rtb));
    >> string fp = Request.PhysicalApplicationPath + "imgtmp\\"
    >> + (Guid.NewGuid()).ToString() + ".jpg";
    >> retImageStream = new System.IO.MemoryStream();
    >> encoder.Save(retImageStream);
    >> retImageStream.Seek(0, System.IO.SeekOrigin.Begin);
    >> ms.Dispose();
    >>
    >> }
    >> }
    >> }
    >>

    >
    >




      My System SpecsSystem Spec

  6. #6


    Jon Davis Guest

    Re: Disposable Canvas?

    Setting AspCompat="true" to the .aspx header to make the page STA threaded,
    and dropping the spawning of a new thread, seemed to alleviate this
    significantly. I executed 5000 times before I just killed the test (was
    running low on drive space -- made that many images). Memory consumption by
    the VS debugger web server did go up to 178MB and more than 1000 handles and
    didn't go down after I stopped the test, so there's still a bad memory leak,
    but not anything like before.

    Would like to fix that lingering memory leak. The stuff HAS to be flushed or
    else it's no good for production use, unless I want to reset IIS every hour
    (which I don't).

    Jon

    "Jon Davis" <jon@REMOVE.ME.PLEASE.jondavis.net> wrote in message
    news:%23JwprXnjHHA.208@TK2MSFTNGP05.phx.gbl...
    > Died with you code, too. I think this has to do with STA threading. Not
    > sure if there is such a thing as a "best practice" for STA threading on
    > ASP.NET.
    >
    > Jon
    >
    >
    > "Jon Davis" <jon@REMOVE.ME.PLEASE.jondavis.net> wrote in message
    > news:exbDR9mjHHA.1776@TK2MSFTNGP05.phx.gbl...
    >>
    >> "Oliver Sturm [MVP C#]" <oliver@sturmnet.org> wrote in message
    >> news:1of44e3mq4rq0$.dlg@sturmnet.org...
    >>> Hi,
    >>>
    >>> Jon Davis wrote:
    >>>
    >>>> OK, why is Canvas not IDisposable, and how do I get rid of all the
    >>>> Windows
    >>>> handles?
    >>>
    >>> I used a variation of your code to try this myself, but I was unable to
    >>> reproduce the crash behaviour your were referring to.

    >>
    >> That's interesting. It might help if I mention I'm trying to do this on
    >> an ASP.NET web page to see about the feasibility of
    >> dynamically-generating images from XAML mark-up, on a heavily impacted
    >> web site. The output of this is great and seems to be fast, it's just
    >> that it crashes after 500 times and IIS's process has 6000 Windows
    >> handles. I'm executing on Windows Vista / IIS 7. Here's the full source.
    >> I'll take a look at yours as well, but in the mean time ... maybe you can
    >> spot something really, really stupid I'm doing?
    >>
    >> using System;
    >> using System.Data;
    >> using System.Configuration;
    >> using System.Collections;
    >> using System.Web;
    >> using System.Web.Security;
    >> using System.Web.UI;
    >> using System.Web.UI.WebControls;
    >> using System.Web.UI.WebControls.WebParts;
    >> using System.Web.UI.HtmlControls;
    >>
    >> namespace ImageGenServer
    >> {
    >> public partial class GenImage : System.Web.UI.Page
    >> {
    >> private System.IO.Stream retImageStream;
    >> protected void Page_Load(object sender, EventArgs e)
    >> {
    >> Gimme();
    >> }
    >>
    >> protected void Gimme()
    >> {
    >> System.Threading.Thread thread = new System.Threading.Thread(
    >> GimmeMore);
    >> thread.SetApartmentState(System.Threading.ApartmentState.STA);
    >> thread.Start();
    >> while (thread.IsAlive)
    >> {
    >> System.Threading.Thread.Sleep(0);
    >> }
    >> Response.ContentType = "image/jpeg";
    >> System.IO.BinaryReader br = new
    >> System.IO.BinaryReader(retImageStream);
    >>
    >> Response.BinaryWrite(br.ReadBytes((int)retImageStream.Length));
    >> br.Close();
    >> retImageStream.Close();
    >> Response.Flush();
    >>
    >> thread = null;
    >> br = null;
    >> retImageStream = null;
    >>
    >> Response.End();
    >> }
    >>
    >> protected void GimmeMore()
    >> {
    >> System.IO.StreamReader sr = new
    >> System.IO.StreamReader(Request.PhysicalApplicationPath + "Window1.xaml");
    >> string xaml = sr.ReadToEnd();
    >> if (Request["text"] != null)
    >> {
    >> xaml = xaml.Replace("{$TEXT$}", Request["text"]);
    >> }
    >> else
    >> {
    >> xaml = xaml.Replace("{$TEXT$}", "Add &quot;text=...&quot;
    >> to querystring.");
    >> }
    >> sr.Close();
    >> System.IO.MemoryStream ms = new
    >> System.IO.MemoryStream(xaml.Length);
    >> System.IO.StreamWriter sw = new System.IO.StreamWriter(ms);
    >> sw.Write(xaml);
    >> sw.Flush();
    >> ms.Seek(0, System.IO.SeekOrigin.Begin);
    >> System.Windows.Controls.Canvas canvas =
    >> (System.Windows.Controls.Canvas)
    >> System.Windows.Markup.XamlReader.Load(
    >> ms);
    >> canvas.Background = System.Windows.Media.Brushes.Yellow;
    >> canvas.Measure(new System.Windows.Size(640d, 480d));
    >> canvas.Arrange(new System.Windows.Rect(0d, 0d, 640d, 480d));
    >> System.Windows.Media.Imaging.RenderTargetBitmap rtb
    >> = new System.Windows.Media.Imaging.RenderTargetBitmap(
    >> 640, 480, 96d, 96d,
    >> System.Windows.Media.PixelFormats.Default);
    >> rtb.Render(canvas);
    >> System.Windows.Media.Imaging.JpegBitmapEncoder encoder
    >> = new System.Windows.Media.Imaging.JpegBitmapEncoder();
    >>
    >> encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(
    >> rtb));
    >> string fp = Request.PhysicalApplicationPath + "imgtmp\\"
    >> + (Guid.NewGuid()).ToString() + ".jpg";
    >> retImageStream = new System.IO.MemoryStream();
    >> encoder.Save(retImageStream);
    >> retImageStream.Seek(0, System.IO.SeekOrigin.Begin);
    >> ms.Dispose();
    >>
    >> }
    >> }
    >> }
    >>

    >
    >




      My System SpecsSystem Spec

  7. #7


    Willy Denoyette [MVP] Guest

    Re: Disposable Canvas?

    "Jon Davis" <jon@REMOVE.ME.PLEASE.jondavis.net> wrote in message
    news:emlLg4ojHHA.4576@TK2MSFTNGP02.phx.gbl...
    > Setting AspCompat="true" to the .aspx header to make the page STA
    > threaded,
    > and dropping the spawning of a new thread, seemed to alleviate this
    > significantly. I executed 5000 times before I just killed the test (was
    > running low on drive space -- made that many images). Memory consumption
    > by
    > the VS debugger web server did go up to 178MB and more than 1000 handles
    > and
    > didn't go down after I stopped the test, so there's still a bad memory
    > leak,
    > but not anything like before.
    >
    > Would like to fix that lingering memory leak. The stuff HAS to be flushed
    > or else it's no good for production use, unless I want to reset IIS every
    > hour (which I don't).
    >
    > Jon
    >



    XAML and WPF is a desktop technology and IMO not designed and not supported
    server side, note that the same applies to System.Windows.Forms. A lot of
    the System.Windows namespace classes need a pumping STA thread to run in,
    and the System.Windows.Markup.XamlReader should throw an exception when
    called from a non-STA thread (don't know why it didn't in your case though).
    The documentation should include a warning just like the one included in
    Windows.Forms
    <Classes within the Windows Forms namespace are not supported for use within
    a Windows service. Trying to use these classes from within a service may
    produce unexpected problems, such as diminished service performance and
    run-time exceptions.
    >




    Willy.


      My System SpecsSystem Spec

  8. #8


    Jon Davis Guest

    Re: Disposable Canvas?

    Oliver,

    I'm running your code in a console app now and watching memory consumption
    go up in a similar way to IIS. Handle count is frozen solid at 151, but
    memory utilization is currently at 271MB at 10000 instances of the loop.
    GC.Collect() after the loop completed had no significant effect; took it to
    245MB on second pass.

    Jon


    "Oliver Sturm [MVP C#]" <oliver@sturmnet.org> wrote in message
    news:1of44e3mq4rq0$.dlg@sturmnet.org...
    > Hi,
    >
    > Jon Davis wrote:
    >
    >> OK, why is Canvas not IDisposable, and how do I get rid of all the
    >> Windows
    >> handles?

    >
    > I used a variation of your code to try this myself, but I was unable to
    > reproduce the crash behaviour your were referring to. I also used a
    > profiler to look out for resource leaks and I didn't find any of these
    > either. Here's the code I used:
    >
    > private void OnButtonClick( object sender, RoutedEventArgs e) {
    > for (int i = 0; i < 1000; i++)
    > GenImageStream();
    > }
    >
    >
    > private static string GetXaml( ) {
    > StreamReader sr = new StreamReader("Canvas.xaml");
    > string xaml = sr.ReadToEnd( );
    > sr.Close( );
    > return xaml;
    > }
    >
    > protected void GenImageStream( ) {
    > string xaml = GetXaml( );
    >
    > using (MemoryStream ms = new MemoryStream(xaml.Length)) {
    > StreamWriter sw = new StreamWriter(ms);
    > sw.Write(xaml);
    > sw.Flush( );
    > ms.Seek(0, SeekOrigin.Begin);
    >
    > Canvas canvas = (Canvas) XamlReader.Load(ms);
    > canvas.Background = Brushes.Yellow;
    > canvas.Measure(new Size(640d, 480d));
    > canvas.Arrange(new Rect(0d, 0d, 640d, 480d));
    > RenderTargetBitmap rtb = new RenderTargetBitmap(
    > 640, 480, 96d, 96d, PixelFormats.Default);
    > rtb.Render(canvas);
    > JpegBitmapEncoder encoder = new JpegBitmapEncoder( );
    > encoder.Frames.Add(BitmapFrame.Create(rtb));
    > using (Stream outstream = new MemoryStream( ))
    > encoder.Save(outstream);
    > }
    > }
    >
    >
    > Oliver Sturm
    > --
    > http://www.sturmnet.org/blog - MVP C#




      My System SpecsSystem Spec

  9. #9


    Jon Davis Guest

    Re: Disposable Canvas?


    "Willy Denoyette [MVP]" <willy.denoyette@telenet.be> wrote in message
    news:70294292-35BA-42AB-99B1-6736FFFB54A3@microsoft.com...
    > XAML and WPF is a desktop technology and IMO not designed and not
    > supported server side, note that the same applies to System.Windows.Forms.


    I know. This was a feasibility test.

    Jon



      My System SpecsSystem Spec

  10. #10


    Jon Davis Guest

    Re: Disposable Canvas?


    "Jon Davis" <jon@REMOVE.ME.PLEASE.jondavis.net> wrote in message
    news:%23ve5NXpjHHA.3940@TK2MSFTNGP02.phx.gbl...
    > Oliver,
    >
    > I'm running your code in a console app now and watching memory consumption
    > go up in a similar way to IIS. Handle count is frozen solid at 151, but
    > memory utilization is currently at 271MB at 10000 instances of the loop.
    > GC.Collect() after the loop completed had no significant effect; took it
    > to 245MB on second pass.
    >
    > Jon


    OK, I think in conclusion a service that does what I'm considering might
    still be feasible but there's some plumbing to be done. If Windows itself
    can clear out the memory when the process dies, which it should (haven't
    tested), I should be able to use IPC to do this through a Windows Service
    that proxies and controls Windows process instances that get reset now and
    then (depending on non-use or memory overload). IIS never gets unloaded but
    now I'm dealing with parallel "cowboy processes".

    Jon



      My System SpecsSystem Spec

Page 1 of 3 123 LastLast
Disposable Canvas?

Similar Threads
Thread Thread Starter Forum Replies Last Post
group elements in canvas Jim .NET General 0 15 May 2009
Canvas does not allow drawing PhredBear Vista General 2 13 Aug 2008
Focusable Canvas =?Utf-8?B?Sm9obiBEdW5u?= Avalon 1 31 Jul 2006
Canvas.GetLeft is NaN NetronProject@gmail.com Avalon 1 07 Jun 2006
3D, Canvas, and Databinding Christopher Bennage Avalon 5 31 May 2006