みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

C#で処理中の状況をStatusLabelに表示

C#で処理中の状況をStatusLabelに表示させたいのですが、どうやらマルチスレッドを使えば良いらしい事は分かったのですが、説明しているページを参考にいろいろやってみたのですがどうもうまくいきません。
例えば次のような場合、10秒後に”9”と表示されて終わってしまうのですが、どの様に書き直せばよろしいでしょうか?
すみません、どなたかご存じの方教えていただけないでしょうか。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace test_multithread3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
toolStripStatusLabel1.Text = i.ToString();
Thread.Sleep(1000);
}
}
}
}

投稿日時 - 2011-11-29 03:01:54

QNo.7160609

暇なときに回答ください

質問者が選んだベストアンサー

まず,Loadイベントは表示前に発生するので,Loadで一生懸命表示をいろいろ切り替えても,
Loadイベントが終わらないと表示されなかったりします。
一応,Shownイベントであれば,初回表示後なので,
Application.DoEventsかませば表示は切り替わります。
ただし,この方法は推奨しません。
Application.DoEventsが必要になった場合,「何かがおかしい」と思った方が良いです。


今回の場合であれば,スレッドよりもタイマーを使って,
処理を分解してしまった方がよい気もします。
# GUIスレッドでSleep使う場合は,通常タイマーを使った状態遷移に修正可能です。


スレッドを使うなら,BackgroundWorkerを使うのが簡単です。

Form1にBackgroundWorkerを貼り付け,
・WorkerReportsProgressプロパティの値をtrueにする
・DoWorkイベントハンドラに,
for (int i = 0; i < 10; ++i)
{
(BackgroundWorkerの名前).ReportProgress(i);
Thread.Sleep(1000);
}
を記述する
・ProgressChangedイベントハンドラに,
toolStripStatusLabel1.Text = e.ProgressPercentage.ToString();
を記述する
・Form1のLoadイベントハンドラに,
(BackgroundWorkerの名前).RunWorkAsync();
を記述する

で,望む動作になると思います。


他にも,Threadクラスを使ったり,デリゲートのBeginInvokeメソッドを使ったり,
Taskクラスを使ったりする方法がありますが,UIへの表示部分がややこしくなるため,
最初はBackgroundWorkerを使うのがよいと思います。

References)
MSDN: BackgroundWorker コンポーネント
http://msdn.microsoft.com/ja-jp/library/c8dcext2.aspx
MSDN: BackgroundWorker クラス
http://msdn.microsoft.com/ja-jp/library/system.componentmodel.backgroundworker.aspx
Blog: Part 4. Visual Studio によるマルチスレッドアプリの開発 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
http://blogs.msdn.com/b/nakama/archive/2009/04/09/part-4-visual-studio.aspx


おまけ) Taskを使う (.NET 4以降)
// using System.Threading.Tasks;
private void Form1_Load (object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
for (var i = 0; i < 10; ++i)
{
Invoke((Action)(() => toolStripStatusLabel1.Text = i.ToString());
Thread.Sleep(1000);
}
}); // var task = new Task(...); task.Start();
}

投稿日時 - 2011-11-29 10:48:46

お礼

丁寧に説明していただき、ありがとうございました。
やってみます。

投稿日時 - 2011-11-29 12:20:00

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

こんにちは。

とりあえず、BackgroundWorker というキーワードで調べてみてください。
提示されているコードでは、Threadの概念自体が理解できてないようですので、もう少し自分で調べた方が、身に付くかと思います・・・。

投稿日時 - 2011-11-29 10:15:43

お礼

まずBackgroundWorkerを勉強してみます。
ヒントをいただけて助かりました、ありがとうございました。

投稿日時 - 2011-11-29 12:16:42

あなたにオススメの質問