![]() |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
| Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks. |
| |||||||
| |
| | #1 (permalink) |
| | 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 Specs![]() |
| | #2 (permalink) |
| | 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 Specs![]() |
| | #3 (permalink) |
| | 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 "text=..." 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 Specs![]() |
| | #4 (permalink) |
| | 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 "text=..." > 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 Specs![]() |
| | #5 (permalink) |
| | 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 "text=..." >> 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 Specs![]() |
| | #6 (permalink) |
| | 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 "text=..." >> 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 Specs![]() |
| | #7 (permalink) |
| | 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 Specs![]() |
| | #8 (permalink) |
| | 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 Specs![]() |
| | #9 (permalink) |
| | 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 Specs![]() |
| | #10 (permalink) |
| | 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 Specs![]() |
| Thread Tools | |
| |
Similar Threads | ||||
| Thread | Forum | |||
| group elements in canvas | .NET General | |||
| Canvas does not allow drawing | Vista General | |||