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

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

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

Re[3]: BackgroundWorkerの処理方法について


(過去ログ 15 を表示中)

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

■5665 / inTopicNo.1)  BackgroundWorkerの処理方法について
  
□投稿者/ さおり (1回)-(2007/07/19(Thu) 20:40:12)

分類:[.NET 全般] 

はじめまして、さおりと言います。

どうしても解決できない所がありみなさんの知恵をかりたいとおもい
投稿させて頂きました。

[処理の内容]
BackgroundWorkerを使い(読み込みファイルが多い為)、ファイルを読込み、datagridviewに表示。

ファイルの内容をグリッドにセットしなければグリッドにちゃんと行が
追加され、正常に表示されるのですが。

GridView.Rows[r].Cells[0].Value = dat.ToString();

を追加して、値をグリッドにセットしようとすると
エラーが表示されてしまいます。

解決方法がありましたら、よろしくお願いします。

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{

string strFileName = (string)e.Argument;

StreamReader sr = new StreamReader(strFileName, System.Text.Encoding.GetEncoding("Shift_JIS"));
while ((dat = sr.ReadLine()) != null)
{
//グリッドに行追加
Thread t = new Thread(new ThreadStart(AddRow));
t.Start();

//ここでエラー:列の追加が上手くいっていない為、
//インデックス範囲外のエラーが表示されます。
GridView.Rows[r].Cells[0].Value = dat.ToString();

}

}

delegate int FocusDelegate();

private void AddRow()
{
Invoke(new FocusDelegate(GridView.Rows.Add));
}

引用返信 編集キー/
■5668 / inTopicNo.2)  Re[1]: BackgroundWorkerの処理方法について
□投稿者/ 囚人 (120回)-(2007/07/19(Thu) 21:59:38)
あまりちゃんと見てませんが、

Thread t = new Thread(new ThreadStart(AddRow));
t.Start();

ここ変じゃないですか?
たとえば、ファイルが100行あったら、スレッドを100個作りたいんですか?
引用返信 編集キー/
■5669 / inTopicNo.3)  Re[1]: BackgroundWorkerの処理方法について
□投稿者/ Hongliang (154回)-(2007/07/19(Thu) 22:22:45)
Hongliang さんの Web サイト
ええと。
せっかく BackgroundWorker を使っているのだから、Thread クラス使うのは止めてください。色々台無しです。
直接 DataGridView のカラムに値を突っ込むより、DataTable に値を突っ込んでいきましょう。それを DataGridView の DataSource にします。

ところで、読み込むファイルは「多い」ですか? 「大きい」ですか?

BackgroundWorker は、主な処理を DoWork イベントで行い、その経過/結果を ProgressChanged / RunWorkerCompleted で GUI に報告します。
BackgroundWorker を使ってコントロールおよびそのコントロールが扱うオブジェクトにアクセスできるのは、ProgressChanged / RunWorkerCompleted イベントのときだけであることに注意してください。
さおりさんがお書きになっているコードでは DoWork 中に DataGridView にアクセスしていますから問題のあるコードということになります。

今回の場合、「主な処理」は「ファイルから読みだすこと」で、「GUI への報告」が「DataGridView の内容の更新」ということになります。もちろん、直接 DataGridView に値を突っ込む場合の行の追加も後者に含まれます。
// DataGridView の DataSource になっている DataTable を操作するのも後者です。

なので、DoWork イベント内ではファイルを読み込み、適当に ReportProgress メソッドを使って ProgressChanged を発生させ、ProgressChanged で DataGridView やら DataTable やらに値を設定する、とか。あんまり細々 ProgressChanged を呼ぶのは拙いですから、適当にタイミングを見計らって。

ファイルが多いってことになると、そもそもこの BackgroundWorker の RunWorkerAsync をどう呼び出しているかって話になりますが……。
引用返信 編集キー/
■5676 / inTopicNo.4)  Re[2]: BackgroundWorkerの処理方法について
□投稿者/ さおり (3回)-(2007/07/20(Fri) 09:40:04)
囚人 さん、Hongliang さん、さっそくの回答ありがとうございます。

私のやりたい処理の説明が不足していたと思います。
読み込んだファイルを1行ごとにGridViewに表示し、GridView_RowsAddedイベント
でスクロールを最下部に設定し、常に追加された行を見れる状態にしたいんです。

囚人 さん
> Thread t = new Thread(new ThreadStart(AddRow));
> t.Start();

BackgroundWorkerでオブジェクトにアクセスする事ができないので、別プロセスで列を追加
させようと思いスレッドを使用しました。スレッドを100個作りたいわけではありません。

Hongliang さん
> 直接 DataGridView のカラムに値を突っ込むより、DataTable に値を突っ込んでいきましょう。それを DataGridView の DataSource にします。

追加された行を常に見たいので、一気にGirdViewに表示すると私のやりたい事と違ってきてしまいます。。。

> BackgroundWorker を使ってコントロールおよびそのコントロールが扱うオブジェクトにアクセスできるのは、
> ProgressChanged / RunWorkerCompleted イベント

ProgressChangedイベントを使用する手もあると思いますが、今回プロセスバーにProgressChangedイベントを
使用しているため、プロセスバーの値が変化しない時はイベントが発生しません。ので常に列が追加されません。


そもそも私がやりたい処理をBackgroundWorkerで行うことはできないのでしょうか?
すみませんが、よろしくお願いします。

引用返信 編集キー/
■5680 / inTopicNo.5)  Re[3]: BackgroundWorkerの処理方法について
□投稿者/ Hongliang (156回)-(2007/07/20(Fri) 11:34:28)
Hongliang さんの Web サイト
>>直接 DataGridView のカラムに値を突っ込むより、DataTable に値を突っ込んでいきましょう。それを DataGridView の DataSource にします。
>
> 追加された行を常に見たいので、一気にGirdViewに表示すると私のやりたい事と違ってきてしまいます。。。

DataTable は事前に DataSource に設定しておけばいいでしょう。DataSource となっている DataTable に行を追加するごとに、自動的に DataGridView も追随して行が追加され追加分のデータが表示されます。RowsAdded イベントも発生します。
// でもどうせ一行読むのに有意の時間がかかるとは思えないけど。

>>BackgroundWorker を使ってコントロールおよびそのコントロールが扱うオブジェクトにアクセスできるのは、
>>ProgressChanged / RunWorkerCompleted イベント
>
> ProgressChangedイベントを使用する手もあると思いますが、今回プロセスバーにProgressChangedイベントを
> 使用しているため、プロセスバーの値が変化しない時はイベントが発生しません。ので常に列が追加されません。

使用する手もあると言うか、使用するしかないといっていいと思います(わざわざ Invoke を使うのは本末転倒)。
ReportProgress メソッドにはちょうど任意のデータを設定できるオーバーロードがあり、ProgressChangedEventArgs.UserState プロパティでそのデータを参照できます。
ProgressChanged のイベントハンドラ内でそれを調べ、DataGridView に値をセットするかあるいはプロセスバー(って ProgressBar ?)の値を変更するか、必要ならその両方を行えばいいのです。
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -