- PR -

グリッドに大量データを表示する際のレスポンス改善について

1
投稿者投稿内容
ひろしくん
会議室デビュー日: 2005/02/15
投稿数: 4
お住まい・勤務地: 愛知県名古屋市中村区名駅
投稿日時: 2006-03-01 19:11
お世話になってます。
現在、VS2003でC#を使ってWindowsアプリケーションを作成しています。

そこで、30Mくらいの大量のデータが記述されているTSVファイルを
StreamReaderを使って読み込んでグリッドに表示しようとしています。

しかし、大量のデータのため、メモリをたくさん使い
画面がフリーズ状態になってしまいます。メモリを増やすことが出来ず、
もっと効率的にデータを取得し表示する方法があればご教授ください。
現在メモリは384Mを使用しています。よろしくお願いします。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-03-01 19:37
引用:

ひろしくんさんの書き込み (2006-03-01 19:11) より:

そこで、30Mくらいの大量のデータが記述されているTSVファイルを
StreamReaderを使って読み込んでグリッドに表示しようとしています。
しかし、大量のデータのため、メモリをたくさん使い画面がフリーズ状態になってしまいます。


一旦読み込んでページ表示にて切り替えるとか。
表示するのにメモリを浪費しているように思えますが違ってたらごめんなさい。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ひろしくん
会議室デビュー日: 2005/02/15
投稿数: 4
お住まい・勤務地: 愛知県名古屋市中村区名駅
投稿日時: 2006-03-02 09:47
早速の返答ありがとうございます。
いろいろ試してみたのですが、なかなかうまく行きません。。
現状は以下の通りです。

ファイルから読み込んだデータを2次元配列に格納し、
その配列をDataSetにセットしてから、グリッドにバインドしています。
string[][] ar;
・・・・
for (int i=0; i < ar.Length; i++)
{
DataSet1.TBL_Sample.Rows.Add(ar[i]);
}
2次元配列にファイルデータをセットした時点で、メモリが急激に増えてしまい、
ファイルの容量の約10倍のメモリを消費してしいます。

他にも、2次元配列に格納せずに直接データセットに格納する方法も試してみたのですが。
StreamReaderで格納するところでメモリも大量に消費してしまいます。

データを読み込む時点でメモリを大量に消費してしまい、
データを表示し終わった後もメモリを消費したままの状態で、困っています。


何万行というデータを画面に表示する仕様自体がおかしいとは思うのですが、
なにか対策等ご存知でしたらご教授ください。
僕のほうでもいろいろ調べてみます。
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2006-03-02 10:10
大量のデータを取り扱うときの基本は、データの管理と表示をWindowsには任せない事です。

例えばDataSetを使わずに、ArrayListを使用するだけでもメモリ消費量はだいぶ減るはずです。ArrayListはデータ型などに関する情報を保持しませんからね。

幸いにもDataGridはArrayListをバインドできるように作られているので、ArrayListの置き換えるだけならそれほど手間はかからないはずです。

引用:

ひろしくんさんの書き込み (2006-03-02 09:47) より:
データを読み込む時点でメモリを大量に消費してしまい、
データを表示し終わった後もメモリを消費したままの状態で、困っています。


それは仕様どおりの正常な動作です。メモリの開放はガベージコレクタが行いますが、実際に開放されるタイミングはOS任せです。直ちに開放される性質のものではありません。

引用:

何万行というデータを画面に表示する仕様自体がおかしいとは思うのですが、
なにか対策等ご存知でしたらご教授ください。


究極的には現在画面上に表示されている部分だけをメモリにロードする事です。しかしそこまで行おうとすれば、コーディング量が大幅に増加します。ArrayListを使うとか、必要なフィールドだけを読み込むのが現実的なラインじゃないかと・・・。

[ メッセージ編集済み 編集者: 甕星 編集日時 2006-03-02 10:14 ]
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2006-03-02 10:10
重複しちゃったので削除

[ メッセージ編集済み 編集者: 甕星 編集日時 2006-03-02 10:11 ]
ひろしくん
会議室デビュー日: 2005/02/15
投稿数: 4
お住まい・勤務地: 愛知県名古屋市中村区名駅
投稿日時: 2006-03-02 21:08
引用:
--------------------------------------------------------------------------------

甕星さんの書き込み (2006-03-02 10:10) より:
例えばDataSetを使わずに、ArrayListを使用するだけでもメモリ消費量はだいぶ減るはずです。
ArrayListはデータ型などに関する情報を保持しませんからね。
幸いにもDataGridはArrayListをバインドできるように作られているので、
ArrayListの置き換えるだけならそれほど手間はかからないはずです。

--------------------------------------------------------------------------------

ArrayListもバインドできるように作られているのですね!
勉強不足ですみません。。

ArrayListを使う方法でいろいろ試してみたのですが、
ArrayListで配列のようなことは出来るのでしょうか?
いろいろ試してみたのですが、実現することが出来ませんでした。

他のスレッドでListクラスなどを使っての実現方法などが書いてあったのですが
うまく実現することは出来ませんでした。

約10万行で、で50列くらい(列も可変)のTSVファイルを読み込もうとしています。。
だんだん調べているうちに限界を感じてきています。

設計のほうに仕様の変更を訴えると共に、解決方法などをこちらのほうでも
調べていこうと思います。よろしくお願いします。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2006-03-02 22:08
引用:

約10万行で、で50列くらい(列も可変)のTSVファイルを読み込もうとしています。。
だんだん調べているうちに限界を感じてきています。



コード:

public class Row
{
public string Field1;
public string Field2;
// :
public string Field50;

public static Row Parse(string line)
{
Row row = new Row();
// 1行分のデータ(line)を分解して row の File1 ~ Field50 を充填。
return row;
}

public static Row[] Load(string fileName)
{
ArrayList list = new ArrayList(10 * 10000);

using (FileStream stream = new FileStream (fileName))
{
using (StreamReader reader = new StreamReader (stream, Encoding.Default))
{
for (;;)
{
string line = reader.ReadLine();
if (line == null) break;

list.Add (Row.Parse (line));
}

reader.Close();
}

stream.Close();
}

return (Row[]) list.ToArray(typeof (Row));
}
}



とかでもメモリが足りなくなったりするわけですか?


_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#

[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2006-03-02 22:09 ]

[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2006-03-02 22:09 ]
1

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