1つだけ過去を変えられるとしたら?

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);
}
}
}
}

A 回答 (2件)

まず,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 …
MSDN: BackgroundWorker クラス
http://msdn.microsoft.com/ja-jp/library/system.c …
Blog: Part 4. Visual Studio によるマルチスレッドアプリの開発 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs
http://blogs.msdn.com/b/nakama/archive/2009/04/0 …


おまけ) 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();
}
    • good
    • 0
この回答へのお礼

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

お礼日時:2011/11/29 12:20

こんにちは。



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

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

お礼日時:2011/11/29 12:16

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!