Hatena::ブログ(Diary)

Yuya Yamaki’s blog このページをアンテナに追加 RSSフィード Twitter

2011年02月22日(火曜日)

デブサミ2011のセッションデモ解説 その1

 デブサミ2011(Developers Summit 2011)のセッション「【18-D-2】Windowsフォームで大丈夫か?一番良いのを頼む。」の資料とデモはこちらの投稿で公開しました。しかしながら、どのようにデモを見たらよいのかがセッションを受講していない方には分からないかと思いましたので、それを解説したいと思います。


 まず、こちらからデモ一式をダウンロードし、展開してください。


  • WPFのレイアウト機能を使った業務アプリ画面
  • パフォーマンス コントロールの描画
  • パフォーマンス データグリッド
  • 日本の業務に適したエディット系コントロール


 この投稿では「パフォーマンス コントロールの描画」デモを解説します。


 フォルダには「WindowsFormsApplication.exe」と「WpfApplication.exe」の2つの実行ファイルが入っていますので、両方実行してください。以後、前者を(A)、後者を(B)と記載します。


f:id:Yamaki:20110222114503p:imagef:id:Yamaki:20110222114502p:image


 (A)のButtonコントロールの[デフォルト]ボタンを押し、開いたウィンドウで[実行]ボタンを押してください。Buttonコントロールを1000個生成して描画するのにかかった時間が表示され、ウィンドウを閉じればその時間が前のウィンドウに結果として表示されるはずです。同じことを(B)でも実施しましょう。すると、実行結果はWindowsフォームの何十分の一の時間になっているはずです。


f:id:Yamaki:20110222132103p:imagef:id:Yamaki:20110222132102p:image


 ここで音声を聞ける環境にある方は音声出力をオンにし、もう一度(B)でボタンコントロールを1000個生成のデモを実行してみましょう。Buttonコントロールが表示される少し前にアラート音がなることを確認できるはずです。実はこのアラート音はストップウォッチを止めたタイミングで鳴らしています。


 では、(B)のTextBoxコントロールの[デフォルト]ボタンを押し、TextBoxを1000個生成するデモ実行してください。Buttonコントロールの時よりもさらに、アラート音が鳴るタイミングと実際にTextBoxが表示されるタイミングのずれが顕著に表れるはずです。


 どのくらいのずれがあるのかを、実際にTextBoxコントロールが表示されたときに[手動計測]ボタンを押して計測してみましょう。


f:id:Yamaki:20110222132613p:image


 このずれが、セッション資料にある「保持モード」を象徴する現象です。


f:id:Yamaki:20110222133458p:image

f:id:Yamaki:20110222133457p:image

f:id:Yamaki:20110222133452p:image


 WPFでは、最終的な描画がメインスレッド(UIスレッド)上で行われません。UIスレッド上ではビジュアルツリーを形成し、描画情報を永続化します。UIスレッドと非同期で、描画スレッドがその永続化された描画情報を基に実際の描画(につながる処理)を行います。そのため、Windowsフォームのようにコントロールの生成が完了したタイミングが描画が行われたタイミングとはなりません。


 この保持モードの利点は、描画のタイミングがアプリケーションのプログラミングに依存しないことです。最終的な描画のタイミングは、Media Integration Layer(MIL)が握っているため、ディスプレイの更新タイミングと同調することができます。


 また、即時モードのGDIでは、高い頻度で再描画を繰り返した際に前の描画を上書きする途中で表示されてしまい、不完全な表示となってしまうことがありました。保持モードでは全体の描画情報がキャッシュされているためこのような現象は発生しません。


 (A)でもう一度Butonコントロールを1000個生成し、上下に激しくスクロールさせてみてください。下の画像のように瞬間的に不完全な描画が行われることが確認できるかと思います。


f:id:Yamaki:20110222133921p:image


 今回のデモの場合、ダブルバッファリングを行うことでこの現象を回避することができますが、その代わりにスクロールスピードは極端に遅くなります。


 なお、WPFでは基本的に最終的な描画をUIスレッドと同期させることはできませんが、UIスレッドの優先度を描画スレッドよりも低く設定することで、疑似的にそのような状態を作り出すことができます。その動作は(B)の[疑似的同期描画]ボタンを押して実行することで確認できます。


 今回のその1はこれでおしまいです。その2では「パフォーマンス データグリッド」のデモを解説します。


ゆうすけゆうすけ 2011/05/06 15:04 はじめまして。
教えてください。
デモにあるWPFの「擬似的同期描画」とはどのようプログラミングして実現しているのでしょうか??
教えて頂ける範囲で結構ですのでよろしくお願いします。

YamakiYamaki 2011/05/06 15:23 ゆうすけさん、ご質問ありがとうございます。

具体的な手法ですが、Dispatcher.Invokeメソッド
http://msdn.microsoft.com/ja-jp/library/ms591593.aspx
を使用してUIスレッドの優先度を下げます。

下記のblogに解説とサンプルプロジェクトがありますので、参考になるかと思います。

WPF rendering thread synchronization | Graeme Hill on .NET development
http://graemehill.ca/wpf-rendering-thread-synchronization

ゆうすけゆうすけ 2011/05/06 20:17 さっそくのご回答をいただきありがとうございます。

DispatcherとThreadを調べていたのですが、ご提示頂いた参考資料は大いに参考になります!

ありがとうございます!

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/Yamaki/20110222/1298356507