ThreadやBackgroundWorkerなどを使用して別スレッドで処理を行うことがありますが、通常の方法では別スレッドからFormにあるコントロールのプロパティなどを操作することは出来ません。
例えば、以下のようにBackgroundWorkerを使用するとします。
BackgroundWorker bw = new BackgroundWorker(); bw.DoWork += new DoWorkEventHandler(bw_DoWork);
以下の処理を「bw.RunWorkerAsync()」によって実行すると実行時にエラーとなります。
void bw_DoWork(object sender, DoWorkEventArgs e)
{
//有効でないスレッド間の操作:
//コントロールが作成されたスレッド以外のスレッドから
//コントロール 'progressBar1' がアクセスされました。
progressBar1.Maximum = 100;
}上記ではプログレスバーのMaximumプロパティを設定していますが、別スレッドから行うことはできません。(プロパティの値を取得することは可能です。)
そこで「Invoke」メソッドを使用します。
Invokeメソッドに渡すDelegate型のメソッドはdelegateで型を定義するか、戻り値、引数が必要ないならMethodInvokerを使用するのが良いでしょう。
MethodInvoker Sample
this.Invoke((MethodInvoker)delegate()
{
progressBar1.Maximum = 100;
}
);引数を必要とする場合の例
まず、渡すメソッドの型を定義します。
delegate void SetPrgrsBarProp(int max, int step);
そして以下がInvokeメソッドに渡すメソッドになります。
SetPrgrsBarProp spbp = (max, step) =>
{
progressBar1.Maximum = max;
progressBar1.Step = step;
};Invokeメソッドにはメソッドとそれに使用する引数を別々に渡します。
this.Invoke(spbp, new object[] {200, 10});Sample Code
上記をまとめたモノですので、Maximumプロパティを2度設定しています。while文でプログレスバーをIncrementしています。
delegate void PrgrsBarIncrement();
delegate void SetPrgrsBarProp(int max, int step);
void bw_DoWork(object sender, DoWorkEventArgs e)
{
this.Invoke((MethodInvoker)delegate()
{
progressBar1.Maximum = 100;
}
);
SetPrgrsBarProp spbp = (max, step) =>
{
progressBar1.Maximum = max;
progressBar1.Step = step;
};
this.Invoke(spbp, new object[] { 200, 10 });
PrgrsBarIncrement pi = () =>
{
progressBar1.Increment(1);
};
while (progressBar1.Value < progressBar1.Maximum)
{
this.Invoke(pi);
Thread.Sleep(50);
}
}





0 Comments:
コメントを投稿