- PR -

リストビューでGDIリーク

1
投稿者投稿内容
いわた
会議室デビュー日: 2005/10/07
投稿数: 16
投稿日時: 2005-10-07 01:51
C#で、リストビューを使用したアプリケーションを開発しているのですが、以下のような現象が
発生して困っています。


[環境]
WindowsXP SP2
.NET Framework 1.1

[概要]
リストビューを詳細表示にして、大量のデータを表示している際に、画面の切り替えやスクロー
ルで再描画がかかるタイミングでGDIオブジェクトの消費が一気に増えてしまうことがある。

[状況]
タスクマネージャでGDIオブジェクトを確認すると、通常は、リストビューの更新時には一時的に
消費量が増加するものの、すぐに元のレベルまで消費量が下がります。
しかし、稀にGDIオブジェクト数がいきなり42億という値まで跳ね上がり、そのまま下がらなくな
ってしまうことがあります。(GC.Collect()を実行しても下がりませんでした)

タスクマネージャの表示上の問題かとも考えたのですが、実際にデスクトップの描画が崩れたり
という現象も出るため、GDIオブジェクトが枯渇しているのは間違いなさそうです。

※3次元CADを使用しているなど、システム全体でGDIの消費量が多い場合に、発生確率が
上がるようです。


ためしに、フォームにリストビューを貼り付けただけのテスト用アプリで確認してみたのですが、
以下のような手順で似たような現象が再現しました。

1.フォームを表示する。
※リストビューは、カラム数が40、行数が10000という状態になっています。
イメージリストは使用していません。

2.横スクロールバーを左右に動かし続ける。

→ タスクマネージャでGDIオブジェクトを確認していると、数値がどんどん上がっていき、10000
を超えた辺りでいきなり42億になる。

また、VB6で同じようなアプリを作成してみましたが、そちらでは同様の現象は確認できませんで
した。

Googleなどで検索してもそれらしい情報は見当たらないのですが、(フォームのアイコンやイメー
ジリスト関連でGDIリークという現象はありましたが、今回の件とは関係なさそうです)どなたか何
かご存知の方はいらっしゃらないでしょうか?


なおこ(・∀・)
大ベテラン
会議室デビュー日: 2004/04/08
投稿数: 174
お住まい・勤務地: 東京都
投稿日時: 2005-10-08 10:41
お世話になります。

「ListView Gdi Leak」で検索してみたら、
海外のサイトがいくつかヒットしましたが、
どれも解決に至っていないような感じでした。

VB6.0については、SP4を当てる事で
この問題を回避できていたようです。
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2005-10-08 12:26
こんにちは。
私は.NET素人ですので、細かいことは分かりませんが…
Windowsアプリ開発の一般論的に言わせていただきます。

リストビューコントロールで、1000件を超えるようなデータを扱う場合は
リソースを大量消費してしまいます。そのためPCに大きな負荷が掛かってしまいます。

しかし、このような大量件数を扱わなければいけないことはよくあることです。
(エクスプローラが良い例でしょう。フォルダに1000を超えるファイルがあることはザラです。)

では、エクスプローラのようなリストビューコントロールで大量データを扱う場合、
どのようにこの問題を回避するかといいますと、
”仮想リストビュー(仮想リストコントロール)”という方法を用います。
この方法ですと、たとえ数万件のデータを扱う場合でも、さほどリソースを消費することがありません。

.NETフレームワークが”仮想リストビュー”をサポートしているか分かりませんが
(MSDNで調べてみましたが、見つけられませんでした。)
私の場合(ネイティブC++で開発)、リストビューで未知数の件数を扱う場合は、
かならず”仮想リストビュー”にしています。

”仮想リストビュー”について知りたい方は、Googleなどで検索してみてください。

いわた
会議室デビュー日: 2005/10/07
投稿数: 16
投稿日時: 2005-10-09 01:38
いわたです。

なおこ(・∀・)様、Tdnr_Sym様、情報ありがとうございます。

確かに海外のサイトだとほとんど同じ現象の報告も上がってますね。探し方が
甘かったみたいです。でもそちらでも解決はしていないんですね・・・。

仮想リストビューの方は、今回は工数的に対応は難しそうですが、まずは
可能かどうかちょっとテストしてみたいと思います。
.NETのリストビューも中身はWin32のリストビューと同じだと思うので、
WndProcをオーバーライドすれば出来ないことは無いと思うのですが。
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2005-10-10 16:31
こんにちは。Tdnr_Symです。

引用:

いわたさんの書き込み (2005-10-09 01:38) より:

仮想リストビューの方は、今回は工数的に対応は難しそうですが、まずは
可能かどうかちょっとテストしてみたいと思います。
.NETのリストビューも中身はWin32のリストビューと同じだと思うので、
WndProcをオーバーライドすれば出来ないことは無いと思うのですが。




どうもやっぱり.NETは標準では仮想リストビューをサポートしていないみたいですね。
次のような仮想リストビューのソースコードを見つけました。

Virtual ListView

サンプルをダウンロードして確認してみましたが、100万件のデータをスムーズに表示しています。C#でWindowProcをオーバーライドすることで、仮想リストビューを自作しているようです。

フリーでライセンスなしのようですので、よろしかったら試してみてはいかがでしょうか。


[ メッセージ編集済み 編集者: Tdnr_Sym 編集日時 2005-10-10 16:55 ]
karajan
ベテラン
会議室デビュー日: 2002/07/05
投稿数: 89
投稿日時: 2005-10-10 18:53
もうすぐ出る.net framework2.0では仮想モード対応してますね。
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2005-10-10 19:36
こんにちは。Tdnr_Symです。

引用:

karajanさんの書き込み (2005-10-10 18:53) より:
もうすぐ出る.net framework2.0では仮想モード対応してますね。



確かにそのような記事が掲載されていますね。ちゃんと読んではいないのですが。

http://www.misterdotnet.com/blog/?p=271
http://weblogs.asp.net/cszurgot/archive/2005/07/05/418092.aspx
いわた
会議室デビュー日: 2005/10/07
投稿数: 16
投稿日時: 2005-10-14 15:10
いわたです。
なかなか検証する時間が取れず、お返事が遅くなりまして申し訳ございません。

Tdnr_Sym様

重ねがさねありがとうございます。サンプルの内容を検証してみました。
チェックボックスを使おうとすると自前で描画する必要がありそうとか、
時々良く分からない例外が発生するとか(サンプルでは空のcatchブロック
で握りつぶしているようですが)いくつか課題はありますが、ほぼ求める
事は実現できそうです。


karajan様

情報ありがとうございます。
.net framework2.0、色々追加されているようで楽しみではあるのですが、
既存資産の検証にかかる手間を考えるとなかなかすぐには手を出しづらい
ですね。まずは趣味の範囲で色々さわってみようかなと思います。

1

スキルアップ/キャリアアップ(JOB@IT)