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

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

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

Re[5]: プログレスバー表示


(過去ログ 125 を表示中)

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

■74542 / inTopicNo.1)  プログレスバー表示
  
□投稿者/ よぽん (1回)-(2015/01/09(Fri) 11:04:47)

分類:[C#] 

フォーム上にボタンとパネルを配置しパネルのVisibleをfalseにします。
そのパネル上にラベルとプログレスバーを配置します。
ラベルのText = "処理中です。"にします。


フォーム上のボタンを押したときに以下の処理を行います。

this.Enabled = false;
panel1.Visible = true;
panel1.Update();
try
{
progressBar1.Maximum = 99999;
progressBar1.Minimum = 0;
for(int inum = 0; inum < 100000; inum++)
{
/* ここには処理を入れる予定です */
progressBar1.Value = inum;
progressBar1.Update();
}
}
finally
{
panel1.Visible = false;
this.Enabled = true;
}

ここで問題なのですが。

プログレスバーの最後までバーの表示ができません。
最後まで表示してからパネル表示を消したいのですが
どうすればよいですか?
引用返信 編集キー/
■74546 / inTopicNo.2)  Re[1]: プログレスバー表示
□投稿者/ 774RR (208回)-(2015/01/09(Fri) 11:37:10)
button1_click のハンドラの中にそのコードを書いちゃったのなら当然の動き。
時間がかかる処理は BackgroundWorker の中に追い出さなきゃ。
http://dobon.net/vb/dotnet/programing/displayprogress.html

引用返信 編集キー/
■74551 / inTopicNo.3)  Re[2]: プログレスバー表示
□投稿者/ よぽん (2回)-(2015/01/09(Fri) 12:54:11)
ありがとうございます。
以下の通り試してみましたが、結果、同じでした

ちなみに
panel1.Visible = false; 行を削除すれば最後まで表示されたものが出る(出っぱなしになる)のですが
panel1.Visible = falseのタイミングがわかりませんでした。

//Button1のClickイベントハンドラ
private void Button1_Click(object sender, System.EventArgs e)
{
//処理が行われているときは、何もしない
if(BackgroundWorker1.IsBusy) return;

//Button1を無効にする
Button1.Enabled = false;

//コントロールを初期化する
ProgressBar1.Minimum = 0;
ProgressBar1.Maximum = 100000;
ProgressBar1.Value = 0;
panel1.Visible = true;
panel1.Update();

//BackgroundWorkerのProgressChangedイベントが発生するようにする
BackgroundWorker1.WorkerReportsProgress = true;
//DoWorkで取得できるパラメータ(10)を指定して、処理を開始する
//パラメータが必要なければ省略できる
BackgroundWorker1.RunWorkerAsync(10);
}

//BackgroundWorker1のDoWorkイベントハンドラ
private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bgWorker = (BackgroundWorker)sender;

//パラメータを取得する
int maxLoops = (int)e.Argument;

//時間のかかる処理を開始する

//ProgressChangedイベントハンドラを呼び出し、コントロールの表示を変更する
for(int i = 0; i < 100000; i++) bgWorker.ReportProgress(i);

//ProgressChangedで取得できる結果を設定する結果が必要なければ省略できる
e.Result = maxLoops;
}

//BackgroundWorker1のProgressChangedイベントハンドラ
private void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//ProgressBar1の値を変更する
ProgressBar1.Value = e.ProgressPercentage;
}

//BackgroundWorker1のRunWorkerCompletedイベントハンドラ//処理が終わったときに呼び出される
private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Error != null)
{
MessageBox.Show("エラー:" + e.Error.Message);
}
else
{
//正常に終了したとき結果を取得する
int result = (int)e.Result;
}
//Button1を有効に戻す
Button1.Enabled = true;
panel1.Visible = false;
}

引用返信 編集キー/
■74562 / inTopicNo.4)  Re[3]: プログレスバー表示
□投稿者/ shu (663回)-(2015/01/09(Fri) 16:42:09)
No74551 (よぽん さん) に返信

BackgroundWorkerの処理がプログレスバーの更新中も
継続して行われるためそのような状態になっていると
思われます。プログレスバーの更新が完了するまで
BackgroundWorker側を待ちの状態にするか
完了後、タイマーでvisibleの変更を遅らせるかするのはどうでしょう。

引用返信 編集キー/
■74565 / inTopicNo.5)  Re[3]: プログレスバー表示
□投稿者/ キム (36回)-(2015/01/09(Fri) 17:40:47)
No74551 (よぽん さん) に返信
プログレスバーの表示は『進捗率を伸ばす場合は』かなり遅延します。
質問者さんの環境が書かれていないので同じかどうか分かりませんが、私の環境では0.7秒くらい。
たぶん、これは滑らかにアニメーションするための仕様だと思います。

なので、単純には BackgroundWorker1_DoWork() の最後で Thread.Sleep(1000) のように待ってあげれば表示されます。

そんなには待ちたくないという場合は、表示の遅延をなくす方法もあるので、それも紹介しておきます。
原理としては、『表示が遅延するのは進捗率を伸ばす場合だけで進捗率を下げる場合は即時表示される』ことを利用します。
詳細は、 http://dobon.net/ さんの
『ProgressBarが徐々に伸びるアニメーションを無効にする』
http://dobon.net/vb/dotnet/control/pbdisableanimation.html
を参考にしてください。

それと何点か気になった点を書いておきます。
・ReportProgressに渡している値が0〜99999です。ProgressBar1.Maximum が100000なので100%にならないです。
・そもそもReportProgressに渡す値はパーセンテージなので0〜100にした方がよいと思います。

ということで、
・ProgressBar1.Maximum を 100とする。
・ReportProgress の呼び出しは bgWorker.ReportProgress((i + 1) * 100 / 100000); とする。
などとすればよいのではないでしょうか。
ただ、これだとまだ無駄にProgressChangedイベントを100000回発生させてしまうままなので、
progressBar1.Value と e.ProgressPercentage が異なる場合だけ progressBar1の値を変更する
処理を行うようにしてください。
出来れば、呼ぶ前に判定する(パーセンテージが上がった場合だけbgWorker.ReportProgress()を呼び出す)
ように最適化したほうがよいです。
その場合は、BackgroundWorker1_DoWork()内でprogressBar1にアクセスするのはまずいので、ローカル変数を用意して管理します。
引用返信 編集キー/
■74567 / inTopicNo.6)  Re[4]: プログレスバー表示
□投稿者/ なちゃ (22回)-(2015/01/09(Fri) 17:54:10)
Vista以降、プログレスバーはなめらかなアニメーションのために、ゆっくり増加するようになっています。
プログレスバーの数値を戻すと一気に描画されるため、値を少し戻すというようなやり方で無理やりあわせることはできます。
もちろんなめらかな動きはしなくなります。

自作のツールでもこういう事して無理やり合わせたりしました。
引用返信 編集キー/
■74643 / inTopicNo.7)  Re[5]: プログレスバー表示
□投稿者/ よぽん (3回)-(2015/01/19(Mon) 11:08:38)
みなさんありがとうございました。

遅れて申し訳ございません。
表示できるようになりました。

まず、BackgroundWorker はやっぱり
使い方がよくわかりません。

なので、
値を増やしてから減らす方法で表示できるようになりました。
でも、100000回表示って数秒無駄に処理かかっちゃうので
キムさんのおっしゃる通り%表示で・・・
ちょっと工夫して10%刻みで表示するようにしました。


解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -