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

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

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

ListViewの高速化


(過去ログ 7 を表示中)

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

■7256 / inTopicNo.1)  ListViewの高速化
  
□投稿者/ L 二等兵(1回)-(2006/10/05(Thu) 14:54:47)

分類:[C#] 


分類:[C#] 

初めまして。
少し質問させてください。

現在、C#でListView(Detail)を用いてファイルの内容を表示させるアプリを開発しているのですが
ファイルの容量が大容量になると、固まってしまいます。
仮想ListViewで実装することも考えたのですが、大容量のファイル読み込み時には仮想ListViewでも重くなることは重くなるようですし
何より仮想ListViewでは列毎のソートが出来ないらしいので、仮想ListViewを使うわけにはいきません。
# 列毎のソートは今回のアプリの必須機能

そこで、マルチスレッドプログラミングを用いて、ファイルの読み込みを別スレッドにすることを考えたのですが
それがどうも上手くいきません。

開発環境はVS2005で、ソースコードはこんな感じです。

<summary>
引数として渡されたファイル名で示されるファイルを解析します。
</summary>
<param name="fileName">ファイル名(絶対パス指定)</param>
private void logRead(string fileName)
{
if (!System.IO.File.Exists(fileName))
{
MessageBox.Show("ファイルがありません。");
}
else
{
logListView.Items.Clear();
// ファイルからログを読み出す。
try
{
using (StreamReader r = new StreamReader(fileName, Encoding.Default))
{
string line;
// 10はListViewのカラム数
string[] logListData = new string[10];

while ((line = r.ReadLine()) != null)
{
logListData[0] = line.Substring(0, 8);
int startPoint = 8;
int endPoint = 0;
ListViewItem subItems = new ListViewItem();
// 空白文字を区切りとして(読み込むファイルは空白文字が区切りとなっている)ログを読み出し、配列に格納する。
for (int i = 1; i < logListData.Length - 1; i++)
{
endPoint = line.IndexOf(" ", startPoint);
logListData[i] = line.Substring(startPoint, endPoint - startPoint);
startPoint = endPoint + 1;
}
logListData[9] = line.Substring(startPoint);
// ListViewに取得した項目を追加する。
for (int i = 0; i < logListData.Length; i++)
{
if (0 == i)
{
// テキスト色設定
switch (logListData[0])
{
case "ERROR ":
subItems.BackColor = Color.LightPink;
break;
case "WARNING ":
subItems.BackColor = Color.LightGreen;
break;
case "INFO ":
break;
case "DEBUG ":
break;
default:
logListView.Items.Clear();
MessageBox.Show("ファイル形式が間違っています。正しいファイルを開いてください。");
return;
}
subItems.SubItems[0].Text = logListData[0];
}
else
{
subItems.SubItems.Add(logListData[i]);
}
}
logListView.Items.Add(subItems);
}
}
}
catch (Exception ex)
{
logListView.Items.Clear();
MessageBox.Show(ex.ToString());
}
}
}

この部分を別スレッドにすればListViewが固まることはないのではないかと思うのですが
やり方が今ひとつわかりません。
delegateとinvokeを使うようなのですが・・・。
ご教授よろしくお願いします。

0
引用返信 編集キー/
■7261 / inTopicNo.2)  Re[1]: ListViewの高速化
□投稿者/ 渋木宏明(ひどり) 二等兵(15回)-(2006/10/05(Thu) 17:18:46)
渋木宏明(ひどり) さんの Web サイト

分類:[C#] 

> 仮想ListViewで実装することも考えたのですが、大容量のファイル読み込み時には仮想ListViewでも重くなることは重くなるようですし

設計と実装次第です。

> 何より仮想ListViewでは列毎のソートが出来ないらしいので、

そんなことはありません。
自分で実装すればいいだけ(しなければならないとも言う ;-p)です。

> そこで、マルチスレッドプログラミングを用いて、ファイルの読み込みを別スレッドにすることを考えたのですが
> それがどうも上手くいきません。

スレッドの扱いに慣れていないなら、BackgroundWorker クラスの使用を検討してみてはどうでしょう?


0
引用返信 編集キー/
■7262 / inTopicNo.3)  Re[2]: ListViewの高速化
□投稿者/ Hongliang 曹長(95回)-(2006/10/05(Thu) 17:28:33)
Hongliang さんの Web サイト

分類:[C#] 

ほかに気になる点は、ListView.Items.Add ですね。
毎回描画が走ってしまうためかなりのコストになります。
一定数ごとに AddRange を呼び出すか BeginUpdate/EndUpdate を使うかすれば結構変わりますよ。
// スレッドとの併用はちょっとだけ面倒ですけど。

0
引用返信 編集キー/
■7264 / inTopicNo.4)  Re[1]: ListViewの高速化
□投稿者/ 魔界の仮面弁士 大尉(173回)-(2006/10/05(Thu) 17:40:53)

分類:[C#] 

> 仮想ListViewでは列毎のソートが出来ないらしいので
そんな事は無いでしょう。単に ListView.Sort が使えないだけですよね。

標準モードの場合に、
 listView1.ListViewItemSorter = ソータ;
 listView1.Sort();
と書いていた処理を、
 内部データ.Sort(ソータ);
 listView1.RedrawItems(…);
のようにすればよいのかな、と。

簡易サンプル。
http://www.vb-user.net/junk/replySamples/2006.10.05.17.31/VirtualListView.cs.txt


> delegateとinvokeを使うようなのですが・・・。

その方法でも良いですが、.NET 2.0 の場合には、「BackgroundWorker クラス」を
使った方が楽ですよ。一般的な“イベント”の形で処理できますので。


最低限使うのは、このあたりのメンバ。

RunWorkerAsync メソッド … 非同期処理を開始する。

DoWork イベント … 時間のかかる処理をここに記述する。
  処理結果は、e.Result のイベント引数に代入する。

RunWorkerCompleted イベント … 非同期処理の完了時に発生。
  ここで、イベント引数 e.Result から結果を受け取り、
  それをコントロール等に反映させる。

0
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -