我正在尝试找出如何将DispatcherObject(在我的情况下是BitmapSource)复制到另一个线程中。
用例:
我有一个WPF应用程序,需要在新线程中显示窗口(实际上是Outlook插件,我们需要这样做是因为Outlook在主UI线程中有一些钩子,并且窃取了某些我们需要使用的热键 - 在Outlook,WPF(我们用于UI)和Winforms(我们需要使用某些由Microsoft提供的Winforms控件)的互操作中“失落在翻译中”)。
因此,我有自己的WPFMessageBox实现,通过设置一些静态属性进行配置 - 其中之一是用于图标的BitmapSource。 这是为了在启动时可以设置WPFMessageBox.Icon一次,从那时起,每个WPFMessageBox都将具有相同的图标。
问题在于,分配给图标的BitmapSource是一个DispatcherObject,当读取时,它会引发InvalidOperationException:“调用线程无法访问此对象,因为不同的线程拥有它”。
如何将该BitmapSource克隆到实际线程中? 它具有Clone()和CloneCurrentValue()方法,但它们不起作用(它们也会抛出相同的异常)。 我还想到了使用originalIcon.Dispatcher.Invoke(在此处进行克隆)-但是BitmapSource的Dispatcher为null,并且仍然-我将在错误的线程上创建副本,仍然无法在我的线程上使用它。 BitmapSource.IsFrozen == true。
有没有想法如何将BitmapSource复制到不同的线程中(而无需完全从图像文件中在新线程中重构它)?
编辑: 因此,冻结没有帮助:最终我有一个BitmapFrame(Window.Icon不需要任何其他类型的ImageSource),当我将其分配为不同线程上的Window.Icon时,即使已冻结,我也会收到InvalidOperationException:“调用线程无法访问此对象,因为不同的线程拥有它。”,并附带以下堆栈跟踪:
用例:
我有一个WPF应用程序,需要在新线程中显示窗口(实际上是Outlook插件,我们需要这样做是因为Outlook在主UI线程中有一些钩子,并且窃取了某些我们需要使用的热键 - 在Outlook,WPF(我们用于UI)和Winforms(我们需要使用某些由Microsoft提供的Winforms控件)的互操作中“失落在翻译中”)。
因此,我有自己的WPFMessageBox实现,通过设置一些静态属性进行配置 - 其中之一是用于图标的BitmapSource。 这是为了在启动时可以设置WPFMessageBox.Icon一次,从那时起,每个WPFMessageBox都将具有相同的图标。
问题在于,分配给图标的BitmapSource是一个DispatcherObject,当读取时,它会引发InvalidOperationException:“调用线程无法访问此对象,因为不同的线程拥有它”。
如何将该BitmapSource克隆到实际线程中? 它具有Clone()和CloneCurrentValue()方法,但它们不起作用(它们也会抛出相同的异常)。 我还想到了使用originalIcon.Dispatcher.Invoke(在此处进行克隆)-但是BitmapSource的Dispatcher为null,并且仍然-我将在错误的线程上创建副本,仍然无法在我的线程上使用它。 BitmapSource.IsFrozen == true。
有没有想法如何将BitmapSource复制到不同的线程中(而无需完全从图像文件中在新线程中重构它)?
编辑: 因此,冻结没有帮助:最终我有一个BitmapFrame(Window.Icon不需要任何其他类型的ImageSource),当我将其分配为不同线程上的Window.Icon时,即使已冻结,我也会收到InvalidOperationException:“调用线程无法访问此对象,因为不同的线程拥有它。”,并附带以下堆栈跟踪:
WindowsBase.dll!System.Windows.Threading.Dispatcher.VerifyAccess() + 0x4a bytes
WindowsBase.dll!System.Windows.Threading.DispatcherObject.VerifyAccess() + 0xc bytes
PresentationCore.dll!System.Windows.Media.Imaging.BitmapDecoder.Frames.get() + 0xe bytes
PresentationFramework.dll!MS.Internal.AppModel.IconHelper.GetIconHandlesFromBitmapFrame(object callingObj = {WPFControls.WPFMBox.WpfMessageBoxWindow: header}, System.Windows.Media.Imaging.BitmapFrame bf = {System.Windows.Media.Imaging.BitmapFrameDecode}, ref MS.Win32.NativeMethods.IconHandle largeIconHandle = {MS.Win32.NativeMethods.IconHandle}, ref MS.Win32.NativeMethods.IconHandle smallIconHandle = {MS.Win32.NativeMethods.IconHandle}) + 0x3b bytes
> PresentationFramework.dll!System.Windows.Window.UpdateIcon() + 0x118 bytes
PresentationFramework.dll!System.Windows.Window.SetupInitialState(double requestedTop = NaN, double requestedLeft = NaN, double requestedWidth = 560.0, double requestedHeight = NaN) + 0x8a bytes
PresentationFramework.dll!System.Windows.Window.CreateSourceWindowImpl() + 0x19b bytes
PresentationFramework.dll!System.Windows.Window.SafeCreateWindow() + 0x29 bytes
PresentationFramework.dll!System.Windows.Window.ShowHelper(object booleanBox) + 0x81 bytes
PresentationFramework.dll!System.Windows.Window.Show() + 0x48 bytes
PresentationFramework.dll!System.Windows.Window.ShowDialog() + 0x29f bytes
WPFControls.dll!WPFControls.WPFMBox.WpfMessageBox.ShowDialog(System.Windows.Window owner = {WPFControlsTest.MainWindow}) Line 185 + 0x10 bytes C#