PC Review


Reply
Thread Tools Rate Thread

Disposable Canvas?

 
 
Jon Davis
Guest
Posts: n/a
 
      4th May 2007
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

 
Reply With Quote
 
 
 
 
Oliver Sturm [MVP C#]
Guest
Posts: n/a
 
      4th May 2007
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#
 
Reply With Quote
 
Jon Davis
Guest
Posts: n/a
 
      4th May 2007

"Oliver Sturm [MVP C#]" <(E-Mail Removed)> wrote in message
news:1of44e3mq4rq0$.(E-Mail Removed)...
> 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();

}
}
}


 
Reply With Quote
 
Jon Davis
Guest
Posts: n/a
 
      4th May 2007
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" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>
> "Oliver Sturm [MVP C#]" <(E-Mail Removed)> wrote in message
> news:1of44e3mq4rq0$.(E-Mail Removed)...
>> 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();
>
> }
> }
> }
>



 
Reply With Quote
 
Jon Davis
Guest
Posts: n/a
 
      4th May 2007
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" <(E-Mail Removed)> wrote in message
news:%(E-Mail Removed)...
> 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" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>>
>> "Oliver Sturm [MVP C#]" <(E-Mail Removed)> wrote in message
>> news:1of44e3mq4rq0$.(E-Mail Removed)...
>>> 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();
>>
>> }
>> }
>> }
>>

>
>



 
Reply With Quote
 
Jon Davis
Guest
Posts: n/a
 
      4th May 2007
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" <(E-Mail Removed)> wrote in message
news:%(E-Mail Removed)...
> 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" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>>
>> "Oliver Sturm [MVP C#]" <(E-Mail Removed)> wrote in message
>> news:1of44e3mq4rq0$.(E-Mail Removed)...
>>> 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();
>>
>> }
>> }
>> }
>>

>
>



 
Reply With Quote
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      4th May 2007
"Jon Davis" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> 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.

 
Reply With Quote
 
Jon Davis
Guest
Posts: n/a
 
      4th May 2007
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#]" <(E-Mail Removed)> wrote in message
news:1of44e3mq4rq0$.(E-Mail Removed)...
> 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#



 
Reply With Quote
 
Jon Davis
Guest
Posts: n/a
 
      4th May 2007

"Willy Denoyette [MVP]" <(E-Mail Removed)> wrote in message
news:70294292-35BA-42AB-99B1-(E-Mail Removed)...
> 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


 
Reply With Quote
 
Jon Davis
Guest
Posts: n/a
 
      4th May 2007

"Jon Davis" <(E-Mail Removed)> wrote in message
news:%(E-Mail Removed)...
> 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


 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Quest: WPF - Troble with Canvas.SetLeft() & Canvas.SetTop()... Brandon Microsoft C# .NET 0 14th Dec 2008 04:15 AM
disposable printer peter Printers 12 15th Jul 2007 10:47 PM
Disposable & 3rd Party Lib & GUI davis Microsoft C# .NET 3 16th Jan 2007 02:09 PM
Disposable Printers ER Printers 15 9th Jul 2005 01:11 PM
Rits Disposable Camera - Computer Hardware 3 3rd Aug 2003 02:08 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 05:55 PM.