Tom*_*fka 5 .net c# wpf exception-handling bitmapsource
我试图弄清楚如何将DispatcherObject(在我的案例中为BitmapSource)复制到另一个线程中.
使用案例:
我有一个需要在新线程中显示窗口的WPF应用程序(该应用程序实际上是Outlook插件,我们需要这样做,因为Outlook在主UI线程中有一些钩子并且正在窃取我们需要使用的某些热键 - 在Outlook,WPF(我们用于UI)和Winforms(我们需要使用某些微软提供的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#
Run Code Online (Sandbox Code Playgroud)
关键是在要使用的线程上创建位图。因此,您无法将图标缓存在某些静态字段/属性中,而是每次在新线程上打开新窗口时加载它(从文件、资源、流或其他内容)。
BitmapFrame 只能在它创建的线程上使用。
正如您正确指出的那样,即使克隆在这里也不起作用(这很糟糕)。
我遇到了完全相同的问题,只需每次加载图标即可解决它,在我的特殊情况下,只需调用
// get your stream somewhere -
window.Icon = BitmapFrame.Create(stream)
Run Code Online (Sandbox Code Playgroud)
这是从 WPF 资源中获取图标的方法:
var streamResourceInfo = Application.GetResourceStream(new Uri(@"pack://application:,,,/YourAssembly;relative path to the icon", UriKind.RelativeOrAbsolute));
// use streamResourceInfo.Stream
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4262 次 |
| 最近记录: |