System.Drawing应该只在WPF的MainWindow线程(C#)上运行吗?

问题描述 投票:0回答:1

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

c# wpf
1个回答
1
投票

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

由于WPF不使用GDI +,因此它具有与System.Drawing命名空间等效的类(例如FontFamilyImageBrushColorConverter)。它们大多数位于System.Windows.Media命名空间。

中。

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

所有WPF UI对象,即从Dispatcher派生的对象,也从Dispatcher继承。 UIElement只能在创建它们的线程上访问实现,否则会引发异常:

调用线程无法访问此对象,因为其他线程拥有它。

这也禁止在线程之间传递DispatcherObject实例,除非这种类型另外从DispatcherObject派生,例如DispatcherObjectFreezable。一旦这些对象处于冻结状态,就可以在线程之间传输它们,因为它们现在已从Freezable分离出来,因此解除了调度程序的亲和力。

这意味着您可以在后台线程上创建图像数据,例如Brush,通过调用ImageSource将其冻结,然后将其传递回UI线程以使用Dispatcher控件进行渲染。

© www.soinside.com 2019 - 2024. All rights reserved.