围绕 SKSwapChainPanel 的 DrawInBackground 属性 进行权衡?
Tradeoffs around SKSwapChainPanel's DrawInBackground property?
我在 UWP/XAML UserControl
中嵌入了 SKSwapChainPanel
。我注意到它有一个 DrawInBackground
属性。我找不到它的文档(只有 3 google results)并假设它可以通过从 UI 线程卸载渲染来提高性能。
但是,如果我想在 PaintSurface
方法中访问 UserControl
的属性(我在其中嵌入了 SKSwapChainPanel
),我需要从 UI线程避免异常The application called an interface that was marshalled for a different thread
.
如果我再次在 UI 线程上分派它(使用 Dispatcher.RunAsync(...)
),它会使 DrawInBackground
属性 变得多余:尽管从技术上讲它允许其余的draw 方法中的调用在后台 运行,我相信取决于 UI 属性的 draw 调用将需要等待 UI 线程到 运行 并且UI 代码部分完成。如果一个线程需要等待/与另一个线程同步,这可能会造成瓶颈。
如何最好地使用 XAML UI 属性,以及 DrawInBackground
属性 的最佳实践是什么?
编辑:
我提到的“XAML UI 属性”是 UserControl
的 FontSize
属性,我在其中嵌入了我的 SkiaSharp canvas,我正在考虑获取 SKSwapChainPanel
的 Height
/ Width
来计算比例因子。最重要的是,我只需要阅读它们,它们确实可以被缓存。我不确定它们是否都提供更改事件,但我确实可以使用 ViewModel 来缓存它。
关于权衡,OP 基本上是正确的 - 它是 UI 的一个单独线程,交互将抛出。我相信这是唯一真正的“缺点”。
我本来想使用一个纯粹的off-UI渲染系统,但问题是有时你想访问UI。
如果您的更新率非常高,那么切换到 non-UI 线程也很好,因为它允许其他控件不间断地 运行。需要知道的一件事是鼠标和键盘交互可能会中断或被高刷新率中断。在这些情况下,最好在后台线程上绘制。
而且,当您必须访问 UI 组件时,有两种方法可以做到这一点 - 都涉及“缓存”类型的样式。您显然知道在 UI 线程上请求调度程序 运行 来读取数据,但这会阻止渲染。
备选方案实际上是阻止和缓存结果。当某些内容发生变化时,您会使缓存无效,下一个循环将读取它。通常,他的数据变化小于 60 fps,因此您会得到一点好处。另一种方法是实际允许来自视图的更新转到与 UI 无关的本地字段或属性。这意味着 UI 更新了一些 cache/state,并且渲染只做一件事 - 尽可能快地渲染。
如果您使用的是视图模型,那么“缓存”可能是 VM 本身,或者如果您需要一些视图 属性 - 例如大小 - 那么您可以订阅大小更改事件并更新本地字段。
我想真正的答案在于你想从UI控件中得到什么并且if/how它们可以被缓存或从一些后台线程访问.让我知道,我可以编辑这个答案。
编辑
您可以使用数据绑定到 private/internal 属性,从您希望跟踪的 属性 到平原,non-observable 属性.他们您不必手动跟踪更改。
对于缩放,大多数视图都有 属性 类型的“比例因子”:https://docs.microsoft.com/dotnet/api/skiasharp.views.uwp.angleswapchainpanel.contentsscale
我在 UWP/XAML UserControl
中嵌入了 SKSwapChainPanel
。我注意到它有一个 DrawInBackground
属性。我找不到它的文档(只有 3 google results)并假设它可以通过从 UI 线程卸载渲染来提高性能。
但是,如果我想在 PaintSurface
方法中访问 UserControl
的属性(我在其中嵌入了 SKSwapChainPanel
),我需要从 UI线程避免异常The application called an interface that was marshalled for a different thread
.
如果我再次在 UI 线程上分派它(使用 Dispatcher.RunAsync(...)
),它会使 DrawInBackground
属性 变得多余:尽管从技术上讲它允许其余的draw 方法中的调用在后台 运行,我相信取决于 UI 属性的 draw 调用将需要等待 UI 线程到 运行 并且UI 代码部分完成。如果一个线程需要等待/与另一个线程同步,这可能会造成瓶颈。
如何最好地使用 XAML UI 属性,以及 DrawInBackground
属性 的最佳实践是什么?
编辑:
我提到的“XAML UI 属性”是 UserControl
的 FontSize
属性,我在其中嵌入了我的 SkiaSharp canvas,我正在考虑获取 SKSwapChainPanel
的 Height
/ Width
来计算比例因子。最重要的是,我只需要阅读它们,它们确实可以被缓存。我不确定它们是否都提供更改事件,但我确实可以使用 ViewModel 来缓存它。
关于权衡,OP 基本上是正确的 - 它是 UI 的一个单独线程,交互将抛出。我相信这是唯一真正的“缺点”。
我本来想使用一个纯粹的off-UI渲染系统,但问题是有时你想访问UI。
如果您的更新率非常高,那么切换到 non-UI 线程也很好,因为它允许其他控件不间断地 运行。需要知道的一件事是鼠标和键盘交互可能会中断或被高刷新率中断。在这些情况下,最好在后台线程上绘制。
而且,当您必须访问 UI 组件时,有两种方法可以做到这一点 - 都涉及“缓存”类型的样式。您显然知道在 UI 线程上请求调度程序 运行 来读取数据,但这会阻止渲染。
备选方案实际上是阻止和缓存结果。当某些内容发生变化时,您会使缓存无效,下一个循环将读取它。通常,他的数据变化小于 60 fps,因此您会得到一点好处。另一种方法是实际允许来自视图的更新转到与 UI 无关的本地字段或属性。这意味着 UI 更新了一些 cache/state,并且渲染只做一件事 - 尽可能快地渲染。
如果您使用的是视图模型,那么“缓存”可能是 VM 本身,或者如果您需要一些视图 属性 - 例如大小 - 那么您可以订阅大小更改事件并更新本地字段。
我想真正的答案在于你想从UI控件中得到什么并且if/how它们可以被缓存或从一些后台线程访问.让我知道,我可以编辑这个答案。
编辑
您可以使用数据绑定到 private/internal 属性,从您希望跟踪的 属性 到平原,non-observable 属性.他们您不必手动跟踪更改。
对于缩放,大多数视图都有 属性 类型的“比例因子”:https://docs.microsoft.com/dotnet/api/skiasharp.views.uwp.angleswapchainpanel.contentsscale