Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
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.

Go Back   Vista Forums > Misc Newsgroups > Avalon

Vista - Disposable Canvas?

 
 
Old 05-04-2007   #1 (permalink)
Jon Davis


 
 

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
Old 05-04-2007   #2 (permalink)
Oliver Sturm [MVP C#]


 
 

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
Old 05-04-2007   #3 (permalink)
Jon Davis


 
 

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
Old 05-04-2007   #4 (permalink)
Jon Davis


 
 

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
Old 05-04-2007   #5 (permalink)
Jon Davis


 
 

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
Old 05-04-2007   #6 (permalink)
Jon Davis


 
 

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
Old 05-04-2007   #7 (permalink)
Willy Denoyette [MVP]


 
 

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
Old 05-04-2007   #8 (permalink)
Jon Davis


 
 

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
Old 05-04-2007   #9 (permalink)
Jon Davis


 
 

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
Old 05-04-2007   #10 (permalink)
Jon Davis


 
 

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
 

Thread Tools


Similar Threads
Thread Forum
group elements in canvas .NET General
Canvas does not allow drawing Vista General


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46