在一个 UI 线程上跨多个 AppDomain 运行 WPF 会出现哪些问题?

发布于 2024-07-14 14:56:58 字数 400 浏览 13 评论 0原文

我们正在考虑创建一个跨多个 AppDomain 运行的 WPF UI。 其中一个应用程序域将运行应用程序,而其余的应用程序域将托管一系列用户控件和逻辑。 当然,这个想法是将这些用户控件和逻辑从主应用程序中沙箱化。

此处是使用 MAF/System 执行此操作的示例。加入。 其他人对此有何经验? 该解决方案如何处理一个用户控件内可能发生的 RoutedEvents/Commands,以及这些是否在 AppDomains 之间正确序列化? WPF 资源怎么样? 可以跨 AppDomain 无缝访问它们吗?

We are looking at creating a WPF UI that runs across multiple AppDomains. One of the app domains would run the application while the remaining AppDomains would host a series of user controls and logic. The idea, of course, is to sandbox these User Controls and the logic away from the main application.

Here is an example of doing this using MAF/System.AddIn. What are some of the experiences other have had with this? How does this solution handle RoutedEvents/Commands that might occur inside one user control and do these get properly serialized across AppDomains? What about WPF resources? Can they be accessed across AppDomains seamlessly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

柒夜笙歌凉 2024-07-21 14:56:58

老问题,但仍然是:您将需要有多个 UI 线程 - 每个 AppDomain 一个。 像这样创建它们:

        var thread = new Thread(() =>
        {
            var app = new Application();
            app.Run();
        });
        thread.Name = AppDomain.CurrentDomain.FriendlyName;
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();

最大的挑战是您无法在 AppDomain 之间发送 FrameworkElement(它们不是 MarshalByRefObject),但您可以使用 FrameworkElementAdapters.ViewToContractAdapter ()ContractAdapterToView() 方法来解决此限制。 有关更多详细信息,请参阅 FrameworkElementAdapters MSDN 页面。

然后,一旦你做到了这一点,恕我直言,最大的问题是你不能在“远程”域的 FrameworkElement 之上放置任何东西(经典的“空域问题”)。 有关详细信息,请参阅此帖子

Old question, but nonetheless: You will need to have multiple UI threads - one per AppDomain. Create them like this:

        var thread = new Thread(() =>
        {
            var app = new Application();
            app.Run();
        });
        thread.Name = AppDomain.CurrentDomain.FriendlyName;
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();

The biggest challenge is then that you cannot send FrameworkElements between AppDomains (they are not MarshalByRefObject), but you can use the FrameworkElementAdapters.ViewToContractAdapter() and ContractAdapterToView() methods to work around this limitation. See the FrameworkElementAdapters MSDN page for more details.

Then, once you have this in place, the biggest problem IMHO is that you cannot lay anything on top of the FrameworkElement from the "remote" domain (the classical "airspace problem"). See this thread for more info about this.

家住魔仙堡 2024-07-21 14:56:58

我回答了一个类似的问题此处并针对WPF进行了编辑,您可以使用合成引擎如何操作的一个有趣的属性是将调度程序泵尾部涂覆到渲染上下文之一中。 这是一个非常轻量级的选择。

另外,我猜您了解 企业库统一

有一个 WPF 应用程序块,因此使用该模式不是痛苦;)但是他们不是说,没有痛苦就没有收获吗?

还有 CAB(复合 UI 应用程序块),与统一相关。 WPF SDK 人员精心制作了 Silverlight 和 SDK。 WPF 平台。 (又名棱镜)。

哦,对了,你还问过资源吗? 我更喜欢在 Application 类中手动加载资源。 我意识到的一件事是,假设您的子文件夹中有一个 ResourceDictionary,并且您正在该 ResourceDictionary 中加载 MergedDictionaries。 因此,如果在您的 Application 类中,您加载“my-res-dir/MergedDictionaryLoader.xaml”(通过代码或 xaml),所有未来的 MERGEDDICTIONARIES 负载均从“my-res-dir”加载

如果您问我,我会认为由于进程当前目录没有更改,您应该为所有其他目录指定“my-res-dir/foo.xaml”,这有点疯狂。 然而事实并非如此(我认为这在任何地方都没有得到很好的记录,恕我直言,应该将其视为错误)。

因此请记住,WPF 资源字典加载将基于当前 XAML 所在的目录。因此,您可以从“my-res-dir”中指定 Source="foo.xaml" /MergedDictionaryLoader.xaml”。 我什至尝试过 URI pack/absolute 语法,但我从未发现它更直观。

I answered a simular question here and edited it for WPF also, you can use an intersting property of how the compisition engine operate's to tail-coat a dispatcher Pump, into one of the rendering contexts. It's a really light weight option.

Also, I'm guessing you know about the enterprise library and unity?

There is a WPF application block so using that pattern is not too painful ;) But don't they say, no pain no gain?

There's also CAB (Composite UI Application Block), ties into unity. The WPF SDK folks have crafted a Silverlight & WPF platform. (a.k.a Prism).

Oh right, also, you asked about Resources? I prefer to load reasources manually in the Application class. One thing I've realized, say you have a ResourceDictionary in a sub-folder and you are loading up MergedDictionaries in that ResourceDictionary. So, if in your Application class, you load "my-res-dir/MergedDictionaryLoader.xaml" (by code or xaml), ALL FUTURE LOADS OF MERGEDDICTIONARIES ARE LOADED FROM "my-res-dir".

Sort of insane if you ask me, I would think that as the process current directory has not changed, you should specify "my-res-dir/foo.xaml" for all your additional directories. However this is not the case (I do not believe this is documented anywhere at least very well and should be considered a bug imho).

So remember, WPF resource dictionary loading is going to be based off of the directory from which the current XAML is in. So you specify Source="foo.xaml" from within your "my-res-dir/MergedDictionaryLoader.xaml". I've even played with the URI pack / absolute syntax, however I've never found that too be much more intuative.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文