C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: DataGirdViewでメモリが解放されない


(過去ログ 39 を表示中)

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■20093 / inTopicNo.1)  DataGirdViewでメモリが解放されない
  
□投稿者/ ぐっちょん (8回)-(2008/06/05(Thu) 16:00:46)

分類:[.NET 全般] 

OS:WINDOWSXP SP2
使用言語:VB.NET2005

度々お世話になります。

データベースからDataReaderで取得したデータをDataGridViewに格納しています。

※コードで表すと以下のような形です。(rowは行変数)
Dim dr As DbDataReader
For i As Integer = 0 To dr.FieldCount - 1
dgv.Rows(row).Cells(i).Value = dr.Item(i)
Next

格納するデータによりますが、
1カラム当たり10バイトのテーブル(合計45カラム)を2000行格納した場合、15M程のメモリを使用します。

新たなデータを表示させる為に、一度DataGridViewのデータを削除して他のデータを表示させると、
元々使用していた15Mのメモリが解放されずに、積み重なるようにメモリが増えてしまいます。(メモリリークが起こっています)

※コードで表すと以下のような形です。
dgv.rows.clear()
dgv.Columns.Clear()

For i As Integer = 0 To dr.FieldCount - 1
dgv.Rows(row).Cells(i).Value = dr.Item(i)
Next

その為、連続使用するとメモリ使用量が膨れ上がってしまう現象があります。
どのように対策を講じれば良いか、教えて頂けますでしょうか。
引用返信 編集キー/
■20094 / inTopicNo.2)  Re[1]: DataGirdViewでメモリが解放されない
□投稿者/ はまや (21回)-(2008/06/05(Thu) 16:16:36)
No20093 (ぐっちょん さん) に返信

Clear()ではなく、Dispose()では駄目ですか?
dgv.Dispose()

最近はDataAdapterによるバインディングのみしか
使っていないので忘れましたが、確かそれで連続で出来ていたと
記憶しています。

引用返信 編集キー/
■20095 / inTopicNo.3)  Re[2]: DataGirdViewでメモリが解放されない
□投稿者/ 囚人 (302回)-(2008/06/05(Thu) 16:32:37)
2000行のデータをオンメモリに持つ是非は置いておいて、放っておいてよいのでは?
GC は即実行はされませんよ。例えば、その15Mのデータ取得を何百回も繰り返して、そろそろやばいとGCが思ったときに実行されますので、ある上限値に達するまでは放置です。
つーか、CLRのヒープが解放されても Windows プロセスのメモリに影響するのかどうか。
何の数値を見てるんでしょうか?
引用返信 編集キー/
■20097 / inTopicNo.4)  Re[3]: DataGirdViewでメモリが解放されない
□投稿者/ ぐっちょん (9回)-(2008/06/05(Thu) 16:47:55)
レスありがとうございます。

>はまやさん
試しにDisposeしてみましたが、特にメモリ使用量に変化はありませんでした。

>囚人さん
むむむ・・勉強不足で単語の理解ができていません。調べてみます。
ようするに、ほっといてもある上限値にきたら勝手に解放されるという事ですか?
見ているものはタスクマネージャにあるパフォーマンスのPF使用量です。
引用返信 編集キー/
■20099 / inTopicNo.5)  Re[1]: DataGirdViewでメモリが解放されない
□投稿者/ 魔界の仮面弁士 (760回)-(2008/06/05(Thu) 16:54:39)
No20093 (ぐっちょん さん) に返信
> dgv.Rows(row).Cells(i).Value = dr.Item(i)
DataGridViewRow のインスタンスから、Cells コレクションを取得し、
その中の i 番目のセルを取得する…という処理を繰り返しているようですが、
それはあまり、効率の良いやり方では無いような気がします。

> メモリリークが起こっています
リークというと、アプリを終了してもメモリ使用量が減らないと言う意味でしょうか?

> 連続使用するとメモリ使用量が膨れ上がってしまう現象があります。
まずは、下記に目を通しておくと良いかも知れません。

[Windows フォーム DataGridView コントロールでのパフォーマンス チューニング]
http://msdn.microsoft.com/ja-jp/library/ms171621.aspx
引用返信 編集キー/
■20102 / inTopicNo.6)  Re[4]: DataGirdViewでメモリが解放されない
□投稿者/ ぐっちょん (10回)-(2008/06/05(Thu) 17:22:52)
レスありがとうございます。

>DataGridViewRow のインスタンスから、Cells コレクションを取得し、
>その中の i 番目のセルを取得する…という処理を繰り返しているようですが、
>それはあまり、効率の良いやり方では無いような気がします。
そうなんですよねー
ただ、DataTableで取得するわけにもいかなくて、
軽い方法で実装するとDataReaderになってしまうのです。
DataReaderで取得したデータをDataGridViewに格納する為に、この方法で実装しています。
(根本から間違ってるかもしれません。少し自信ない)

>リークというと、アプリを終了してもメモリ使用量が減らないと言う意味でしょうか?
はい、メモリリークの使い方が間違っていたようです。
アプリを終了すると、メモリは解放されます。
アプリを実行している間に、メモリ使用量が蓄積されていきます。

>まずは、下記に目を通しておくと良いかも知れません。
見てみます。
引用返信 編集キー/
■20106 / inTopicNo.7)  Re[5]: DataGirdViewでメモリが解放されない
□投稿者/ 魔界の仮面弁士 (761回)-(2008/06/05(Thu) 19:42:47)
2008/06/05(Thu) 19:45:32 編集(投稿者)

No20102 (ぐっちょん さん) に返信
>> DataGridViewRow のインスタンスから、Cells コレクションを取得し、
>> その中の i 番目のセルを取得する…という処理を繰り返しているようですが、
> ただ、DataTableで取得するわけにもいかなくて、

DataReader で得たデータを DataTable に格納して使ってはいけないのでしょうか?
今のままだと、DataGridView 内には件数分の行インスタンスが生成されることになりますが、
データバインドを使えば、DataGridView では行のインスタンスを共有させる事ができるため、
メモリ効率が良くなるように思えます。


それと、私が先に書いたのは、データバインドの事を指しているわけではなく、
プロパティの参照回数を減らした方が良いのでは無いか、という意図のものでした。

たとえば、
 DataGridView1.Rows(0).Cells(0).Value = data
とするかわりに、
 DataGridView1(0, 0).Value = data
とすると、プロパティの参照回数を抑える事ができるかと思います。

前者だと、DataGridView → DataGridViewRowCollection → DataGridViewRow
→ DataGridViewCellCollection → DataGridViewCell → Object という順序で
参照されていきますが、後者の書き方にすれば、それぞれのプロパティ参照は
DataGridView → DataGridViewCell → Object という手順で済むので、
コレクションを毎回取得する手間がわずかながらも省略できるかな、と。


あるいは、Rows や Cells などの参照を、ループ内で毎回繰り返させるのではなく、
それらを変数にキャッシュしておいて
 Dim cells As DataGridViewCellCollection
 cells = DataGridView1.Rows(row).Cells
 For i As Integer = 0 To dr.FieldCount - 1
  cells(i).Value = dr(i)
 Next
という書き方にする手法もあるかと思います。
(いずれにしても、データバインドにした方が効率は良いと思いますけれども)


> 軽い方法で実装するとDataReaderになってしまうのです。
(ASP.NET などのように)シーケンシャルなアクセスで良い場合には都合が良さそうですが、
今回のように、対象データすべてを表示させなければならないような状況においては、
むしろ効率が悪いかも知れません。セルを For で列挙するコストも馬鹿にならないので。

DataReader から 個別のセルに割り当てる今の方法と、(DataAdapter 等から)
DataTable に取り込んだものをバインドさせる方法とで、それぞれの
処理速度およびメモリ効率について、比較実験してみてはいかがでしょう。


> アプリを実行している間に、メモリ使用量が蓄積されていきます。
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=1944927&SiteID=7
引用返信 編集キー/
■20107 / inTopicNo.8)  Re[5]: DataGirdViewでメモリが解放されない
□投稿者/ Jitta on the way (107回)-(2008/06/05(Thu) 19:43:46)
No20102 (ぐっちょん さん) に返信
> レスありがとうございます。
>
> >DataGridViewRow のインスタンスから、Cells コレクションを取得し、
> >その中の i 番目のセルを取得する…という処理を繰り返しているようですが、
> >それはあまり、効率の良いやり方では無いような気がします。
> そうなんですよねー
> ただ、DataTableで取得するわけにもいかなくて、
> 軽い方法で実装するとDataReaderになってしまうのです。
> DataReaderで取得したデータをDataGridViewに格納する為に、この方法で実装しています。
> (根本から間違ってるかもしれません。少し自信ない)

なぜ、DataTable で取得出来ないのでしょう?
軽い方法とは?何にたいして、何が軽いのでしょう?
引用返信 編集キー/
■20122 / inTopicNo.9)  Re[6]: DataGirdViewでメモリが解放されない
□投稿者/ ぐっちょん (11回)-(2008/06/06(Fri) 10:22:13)
2008/06/09(Mon) 10:09:00 編集(投稿者)
2008/06/09(Mon) 10:08:57 編集(投稿者)

>DataReader で得たデータを DataTable に格納して使ってはいけないのでしょうか?
この方法が出来るとは考えていませんでした。
グーグル先生に問い合わせてみます。
DataTableに格納するまでがネックになっていたので(※下記で説明します)
この方法が実現できれば、こちらで実装できそうです。


>たとえば、
> DataGridView1.Rows(0).Cells(0).Value = data
>とするかわりに、
> DataGridView1(0, 0).Value = data
>とすると、プロパティの参照回数を抑える事ができるかと思います。
なんと!
この書き方一つで参照回数が変わってくるのですか
参考にさせて頂きます。


>DataReader から 個別のセルに割り当てる今の方法と、(DataAdapter 等から)
>DataTable に取り込んだものをバインドさせる方法とで、それぞれの
>処理速度およびメモリ効率について、比較実験してみてはいかがでしょう。

>なぜ、DataTable で取得出来ないのでしょう?
>軽い方法とは?何にたいして、何が軽いのでしょう?

DataAdapterからFillを実行して、DataSetを取得して、DataTableを取得する方法を行っていましたが、
Fillを実行してDataSetを取得するときに、莫大なメモリを消費してしまうのです。
取得するデータ数にもよりますが、数百Mのメモリを消費する場合、パソコンはフリーズします。

※コードで表すと以下のような形です。
Dim cmd As DbCommand 'system.Data.Common.DbCommand
cmd.CommandText = commandText 'SQL文

Dim da As DbDataAdapter
da.SelectCommand = cmd
ds = New DataSet()
da.Fill(ds) 'ここで固まります

その為、DataReaderで取得しています。


>http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=1944927&SiteID=7
処理を連続して行い、パフォーマンスとタスクマネージャから調べてみました。
結果、一定の箇所に来たところで、GCが実行されました(メモリ解放されました)
お騒がせしましたorz

メモリが解放されない問題につきましては、お蔭様で解決致しました。ありがとうございます。
(解決済にした方がいいのかな?)

※解決済にしておきます
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -