在ASP.NET中将WPF对象呈现为图形

3
我正在尝试在ASP.NET图像处理程序中将基于WPF的对象呈现为PNG。我们创建了一个WPF设计器,用于创建基于XAML的模板。使用XAML序列化器将模板存储到磁盘上很简单。但是,在ASP.NET HTTP处理程序中拉取相同的序列化XAML对象并重新组合它们却很困难。
XAML反序列化过程需要在STA线程上运行。创建一个线程并将其设置为STA,并进行反序列化和图像合成的操作,第一次可以工作。我得到了重构后的基于XAML的图像,并将其传回并发送给浏览器。然而,后续的HTTP处理程序调用会导致Web服务器崩溃,并显示错误消息“The calling thread cannot access this object because a different thread owns it.”
是否有任何库可以从简单的基于XAML的对象生成图像?
3个回答

2
我之前在 MSDN 论坛上回答过这个问题(链接),但我会将其复制并进行调整,以便 StackOverflow 的后来者也能受益。 :)
最简单的方法是每次启动一个新的 STA 线程,让它处理一张图片,然后线程终止并清理所有内容。但是,这样做不会真正扩展得很好,因为线程的启动成本以及所有 WPF Dispatcher 基础结构设置都会增加明显的开销。你需要考虑拥有一个渲染就绪线程池,把作业分配给它们。你应该可以基本上启动只调用 Dispatcher::Run 的线程,并让它们保持运行状态。当作业到达时,你从池中取出一个线程,并在相关的 Dispatcher 实例上调用 Invoke(可以通过调用 Dispatcher::FromThread 获取此实例),传递包含你想要在该线程上下文中执行的所有渲染逻辑的委托。当完成时,线程将保持运行状态,因为你早先调用了 Disptacher::Run,你可以将其返回到池中供下一个作业使用。要清理线程,只需转到它们并调用 Dispatcher::InvokeShutdown。

谢谢Drew。我正在使用一个简单的STA线程配置,就像你描述的那样。我会考虑拥有一组渲染准备好的线程来分配任务。 - KenBobPDX
是的,如果你希望以任何方式扩展,这是绝对必要的。祝你好运! :) - Drew Marsh
1
谢谢你,Drew。你能给我指一些这样的线程池的例子吗?当涉及到管理线程池时,我有点新手。非常感谢你的帮助。 - KenBobPDX
让我们深入研究Stack Overflow[1]。 :) 只需记住,您需要将池的线程设置为STA,并在每个线程上初始化Dispatcher。[1] https://dev59.com/snRC5IYBdhLWcg3wAcbU - Drew Marsh
我发现在创建的线程上不需要初始化调度程序;它们会自动设置。但是,您确实需要对它们进行手动清理。 - RandomEngy
啊,是的,我忘记了它们会在你第一次调用Dispatcher::CurrentDispatcher时自动为你创建Dispatcher。 - Drew Marsh

2

我有一些示例代码,在类似问题的答案中。尽管Drew指出,通过向线程传递委托来重用线程可能更好。此外,我认为你可以使用XamlReader.Parse()而不是编程创建。


我正在使用XamlReader.Parse()用于可观察集合中的模板片段。非常好的例子。非常感谢! - KenBobPDX

0

您有考虑过创建一个WPF外壳应用程序,仅加载您创建的模板,对其进行截屏,然后将截图保存到磁盘吗?然后允许该应用程序接受命令行参数,并传递要渲染的模板和要生成的文件名称。

然后,您的Web应用程序可以将其作为单独的进程启动,等待其完成,然后获取文件。这样,您就不必担心运行多个STA线程的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接