I am trying to figure out how to copy DispatcherObject (in my case, BitmapSource) to another thread.
Use Case:
I have a WPF application that should show the window in a new thread (the application is actually an Outlook add-on, and we need to do this because Outlook has some interceptions in the main UI thread and steals some hot keys that we need to use - "lost" in translation "in the Outlook interface, WPF (which we use for the user interface) and Winforms (we need to use certain winforms controls provided by Microsoft).
In doing so, I have my WPFMessageBox implementation that is configured by setting some static properties - and one of them is BitmapSource for the icon. This is used so that at startup I can install WPFMessageBox.Icon once, and from then on, each WPFMessageBox will have the same icon.
The problem is that the BitmapSource that is assigned to the icon is a DispatcherObject, and when reading it will throw an InvalidOperationException: "The calling thread cannot access this object because it has a different thread."
How can I clone this BitmapSource into an actual stream? It has the Clone () and CloneCurrentValue () methods that do not work (they also throw the same exception). I also had to use originalIcon.Dispatcher.Invoke (do the cloning here), but Disputcher BitmapSource is NULL, and yet - I would create a copy on the wrong thread and still could not use it on mine. BitmapSource.IsFrozen == true.
Any idea on how to copy BitmapSource to another stream (without completely reconstructing from the image file in the new stream)?
EDIT: So freezing doesn't help: I ββend up with a BitmapFrame (Window.Icon doesn't use any other ImageSource type anyway), and when I assign it as Window.Icon in another thread, even if frozen, I get InvalidOperationException : "The calling thread cannot access this object because another thread belongs to it." with the following stack trace:
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#