c# - System.Drawing 是否应该仅在 WPF 的 UI 线程(C#)上运行?

标签 c# wpf

我正在 Visual Studio 中开发基于 C# + WPF 的应用程序,给出的建议是仅在 UI 线程上运行 System.Drawing 相关方法(例如使用 SynchronizationContext)。 我使用 System.Drawing 执行的一些任务包括:创建位图图像、在其他图像对象和位图对象之间进行转换、使用 Graphics 在位图上绘制并保存它们。 然而,由于图像操作占用了线程,因此可以从 GUI 窗口卡住中注意到许多操作。这会影响用户体验,并且会增加项目的复杂性。 那么,使用其他线程执行 System.Drawing 工作是否有问题?谢谢。

最佳答案

正如评论已经指出的,System.Drawing 命名空间以 WinForms 为目标,并且仅包含其渲染平台特定的 GDI+ 对象。这些对象不是线程安全的。因此,应避免在多线程上下文中处理它们,因为副作用是不可预测的。

由于 WPF 不使用 GDI+,因此它有自己的类,相当于 System.Drawing 命名空间(例如,FontFamilyImage画笔ColorConverter)。其中大部分位于System.Windows.Media命名空间中。

在 WPF 中,线程关联性由 DispatcherObject 强制执行。 。由于 DispatcherObjectDispatcher 关联。并且 Dispatcher 对象与线程关联,我们也可以说调度程序亲和性

所有 WPF UI 对象,即从 UIElement 派生的对象,也继承自 DispatcherObjectDispatcherObject实现只能在创建它们的线程上访问(调度程序亲和性),否则会引发异常:

The calling thread cannot access this object because a different thread owns it.

这也禁止在线程之间传递 DispatcherObject 实例,除非此类型另外派生自 Freezable例如,BrushImageSource
一旦这些对象处于卡住状态,它们就可以在线程之间传输,因为它们现在已与调度程序分离,因此调度程序亲和性已被解除。

这意味着您可以在后台线程上创建图像数据,例如 System.Windows.Media.Imaging.BitmapSource,通过调用 BitmapSource.Freeze() 卡住它并将其传回 UI 线程以使用 Image 控件进行渲染。

关于c# - System.Drawing 是否应该仅在 WPF 的 UI 线程(C#)上运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59794174/

相关文章:

c# - 在不同的 ViewModel 之间共享数据

C# .NET 相当于 PHP time()

wpf - 只是我,还是 WPF 是一堆数据绑定(bind)和自定义 IValueConverters?

c# - WPF DataGrid 中类似 Excel 的选择矩形

c# - Owin 是否也可以处理其管道中的响应

c# - 如何在 UWP 中为路径控制创建共享样式?

c# - 如何获取正在监听特定端口 LAN 的所有服务器的 IP?

WPF插件创建UI策略

wpf - 如何在 Expression Blend 中更改不同状态的按钮文本颜色?

wpf - 根据组合框选择使按钮可见