3

...また...

「私はWPFの奥底でどんな悪を目覚めさせたのですか?」

バックグラウンド スレッドで Canvas を作成し、それをビットマップにレンダリングしています。私はこれを本番コードで1年以上問題なく動作させてきました。私は次のことを行います:

  • キャンバス オブジェクトを作成する
  • 新しい NameScope オブジェクトを作成する
  • その NameScope を Canvas に割り当てます
  • キャンバスに好きなものを描きます
  • キャンバスのサイズで canvas.Measure() を呼び出します
  • Canvas の使用可能な矩形で canvas.Arrage() を呼び出します
  • canvas.UpdateLayout() を呼び出します
  • キャンバスをレンダリングする

描画ステップでは、常に canvas.Children.Add() を呼び出して、UIElements を Canvas に配置しました。これは常に機能しています。

現在、何らかの不可解な理由により、私が取り組んでいるアプリケーションの特定のケースで、canvas.Children.Add() への呼び出しが無期限にハングし、バックグラウンド スレッドがブロックされます。1年以上動作しているコードと、この1つの特定のケースとの間で、私が違うことをしているとは思えません。

canvas.Children.Add() への呼び出しがこのようにハングする理由を誰かが提案できますか?

編集: バックグラウンド スレッドは STA スレッドです (MTA スレッドで WPF を使用して画像を処理できなかったため、バックグラウンド スレッド処理モデルが導入されました)、スレッド アパートメント モデルが原因であってはなりません。

編集 #2 : バックグラウンド スレッドから Dispatcher.BeginInvoke() を試すことを人々が提案している理由は理解していますが、次の 2 つの理由から、そのオプションは好きではありません。

  1. バックグラウンド スレッドの処理をそのスレッドで同期させたい。私のバックグラウンド スレッドには、他のスレッドがイメージ ジョブを送信するキューがあり、私のバックグラウンド スレッドは、各ジョブに到達したときに各ジョブを処理します。Dispatcher.BeginInvoke() を使用すると、避けたい別の複雑なレイヤーが追加されます。
  2. 私は今までする必要はありませんでした。このバックグラウンド処理をバックグラウンド スレッドで同期的に行うと、うまくいきました。私は、このコードが機能しない原因となるこの奇妙なエッジ ケースについて、何が異なる可能性があるかを判断しようとしています。うまくいかない場合は、WPF を使用せずにこの処理コードを書き直すことになりますが、これも避けたいと思います。
4

2 に答える 2

2

バックグラウンド スレッドに使用しているアパートのモデルは何ですか?

WPF は STA スレッドで実行する必要があると思います。バックグラウンド スレッドを生成するときは、そのアパートメントを STA に設定してみてください。

アップデート:

STA スレッドに問題がない場合は、キャンバスの描画をチャンクに分割してみます。基本的に次のことを行う場合:

Dispatcher.BeginInvoke(...)

スレッドから、指定されたデリゲートがディスパッチャー キューの後ろにプッシュされ、キューに入れられた他のタスクを実行できるようになります。

更新 2:

.NET フレームワークのリファレンス ソースを使用して、Canvas オブジェクトのソース コードをデバッグすることもできます。これを有効にするには、[ツール] -> [オプション] のデバッグ オプションで [.net フレームワーク ソースのステッピングを有効にする] をオンにします。

于 2009-04-29T17:15:46.583 に答える
-1

バックグラウンド スレッドで Dispatcher.Run() を呼び出してみてください。

于 2009-04-29T17:42:10.623 に答える