BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース マルチスレッドとWPF 4.5

マルチスレッドとWPF 4.5

原文(投稿日:2012/01/23)へのリンク

WPF 4.5ではマルチスレッド・データバインディングのサポートが改善されたが、このテクニックには依然としてリスクがある。この記事では、それがどのように動いているか、安全に使うには何が必要かについて説明する。

WPFデータバインディングはこれまでマルチスレッドを場当たり的にサポートしてきた。オブジェクトがプロパティ変更イベントを非UIスレッドで発行すると、データバインディング・インフラストラクチャが動き出す。通常これはうまくいくのだが、潜在的な競合状態のため、これは実際のところ安全ではない。コンピュータサイエンスの観点から、スレッドをまたがるアクセスを単純に許さない方が適切だろう。これは実のところコレクション変更イベントのケースだ。

残念なことに、開発者は常に正確さを気にしているわけではない。ただやりたいことをやるだけだ。その結果、「スレッドセーフ」もしくは「ディスパッチャーセーフ」なオブザーバブル・コレクションについて、さまざまな試みがなされてきた。これらの試みの基本設計はすべて、呼び出し前にコレクション変更イベントを適切なスレッドにマーシャルするというものだ。この場合、適切なスレッドとは、ディスパッチャーが実行しているいずれかのスレッドになる。残念ながら、これでは競合状態の可能性はなくならない。

MicrosoftはWPF 4.5でもっと安全な代替手段を開発者に提供している。BindingOperations.EnableCollectionSynchronizationを呼び出すことにより、WPFデータバインディングエンジンはロックを利用する。デフォルトでは、さきほどの呼び出しに指定されたオブジェクトでロックを獲得するが、もっと複雑なロックスキームを使うオプションもある。残念ながら、これは間違いやすいテクニックだ。バックグラウンドスレッドにおいて、コレクションのロックを獲得するのは忘れてしまいやすい。また、コレクションが不要になったときに、コレクション同期を無効にするのを忘れる可能性 もある。これはメモリーリークを引き起こすだろう。

このテクニックのもうひとつの問題は、個々のオブジェクトをプロテクトしないことだ。したがって、コレクションがロック下で読み出されているあいだ、コレクションに含まれるアイテムのプロパティは必ずしも安全に読み出されるわけではない。これはアトミックにできないゲッターやプロパティ(たとえば大きな値の型)の場合に問題になるだろう。

コレクションをアップデートするのにバックグラウンドスレッドを使っている人には、そのコレクションでイミュータブルオブジェクトだけを使うことを強く推奨する。あるいは、もしオブジェクトをイミュータブルにできないのなら、少なくともプロパティのゲッターをスレッドセーフにするよう、細心の注意を払うべきだ。そして、いざとなれば、この機能の存在を忘れて、コレクションのアップデートをUIスレッドにマーシャルするだけにした方がよいだろう。

この記事に星をつける

おすすめ度
スタイル

BT