3

I'm trying to render a WPF based object as a PNG inside an ASP.NET image handler. We've created a designer in WPF that creates XAML based templates. Using the XAML serializer to store the templates on disk is simple. Pulling those same serialized XAML based objects and reconstituting them in an ASP.NET HTTP handler has proved difficult.

The XAML deserialization process needs to run on a STA thread. Creating a thread and setting it to STA and doing the deserialization and image composition worked, the first time. I get the reconstituted XAML based image created, passed back and sent to the browser. Subsequent calls to the HTTP handler crash the web server with "The calling thread cannot access this object because a different thread owns it."

Are there any libraries out there that will generate an image from a simple XAML based object?

3 Answers 3

2

I had answered this a while ago on the MSDN forums, but I'll copy that and tweak here for the prosterity of StackOverflow. :)

The simplest approach is spinning up a new STA thread everytime, letting that process one image and then the thread terminates and everything is cleaned up. That won't really scale so great though as the spin-up costs for the thread as well as all WPF Dispatcher infrastructure setup will add obvious overhead. You would want to look into having a pool of render ready threads that you farm the jobs out to. You should be able to basically spin up threads that just call Dispatcher::Run, and leave them sitting there. When a job comes in, you basically pull a thread out of the pool and call Invoke on the associated Dispatcher instance (you can get this by calling Dispatcher::FromThread) passing a delegate that contains all the rendering logic you want to execute in the context of that thread. When that finishes, the thread will remain running, because of Disptacher::Run call you made earlier, and you can return it to the pool for the next job to use. To clean up threads, just go to them and call Dispatcher::InvokeShutdown.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks Drew. I am using a STA thread in a simple configuration as you described. I'll look into having a pool of render ready threads to farm the jobs out to.
Yes, if you hope to scale in any way, it's an absolute must. Good luck! :)
Thanks again Drew. Can you point me to any examples of such a thread pool? I'm a bit of a neophyte when it comes to managing thread pools. I really appreciate your help.
Let's recurse into Stack Overflow[1]. :) Just keep in mind you need to set your pool's threads to be STA and initialize the Dispatcher on each of them. [1] stackoverflow.com/questions/435668/…
I've found you don't need to initialize the Dispatcher on the created threads; they get set up automatically. You do need to do manual cleanup on them however.
|
2

I have some example code in an answer to a similar question. Though as Drew pointed out, you would probably be better off re-using your threads by passing delegates to them. Also I think you could use XamlReader.Parse() instead of programmatic creation.

1 Comment

I'm using XamlReader.Parse() for pieces of the template in an observable collection. Excellent example. Thank you very much!
0

Have you considered creating a WPF shell application that just loads the templates you've created, screen shots them, and then saves the screenshot to disk? Then allow the application to accept command line args and pass in the template you want it to render and the name of the file you want it to generate.

Your web app could then just spin it off as a separate process, wait for it to complete, and grab the file. That way you wouldn't have to worry about running multiple STA threads.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.