DispatcherObject (私の場合は BitmapSource) を別のスレッドにコピーする方法を見つけようとしています。
ユース ケース:
新しいスレッドでウィンドウを表示する必要がある WPF アプリがあります (アプリは実際には Outlook アドインであり、Outlook のメイン UI スレッドにいくつかのフックがあり、使用する必要がある特定のホットキーを盗んでいるため、これを行う必要があります。 - Outlook、WPF (UI に使用)、および Winforms (Microsoft が提供する特定の winforms コントロールを使用する必要があります) の相互運用における「翻訳で失われた」。
これで、いくつかの静的プロパティを設定することで構成された WPFMessageBox の実装ができました。そのうちの 1 つはアイコンの BitmapSource です。これは、起動時に WPFMessageBox.Icon を一度設定できるようにするために使用され、それ以降、すべての WPFMessageBox が同じアイコンを持つようになります。
問題は、icon に割り当てられている BitmapSource が DispatcherObject であり、読み取り時に InvalidOperationException をスローすることです: "別のスレッドが所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません。".
その BitmapSource を実際のスレッドに複製するにはどうすればよいですか? Clone() および CloneCurrentValue() メソッドがありますが、機能しません (同じ例外がスローされます)。originalIcon.Dispatcher.Invoke( ここでクローンを作成する ) を使用することも思いつきましたが、BitmapSource の Dispatcher は null であり、それでも - 間違ったスレッドでコピーを作成し、それを自分では使用できませんでした。BitmapSource.IsFrozen == true。
BitmapSource を別のスレッドにコピーする方法についてのアイデアはありますか (新しいスレッドのイメージ ファイルから完全に再構築せずに)。
編集: したがって、フリーズは役に立ちません:最終的には BitmapFrame (Window.Icon は他の種類の ImageSource を取りません) を持っています。 、私は 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#