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:
コメントを投稿