スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[C#] ToolStripコントロールのInvokeの使い方

.NET開発(C#)で、Invokeでハマったのでメモします。

ハマった部分は、form以外のクラスから別スレッドを作り、
そのスレッドから、formのToolStrip系のコントロールを操作するところです。


別スレッドからフォーム上のコントロールを操作すると、適切な処理をしていないと、

InvalidOperationExceptionはハンドルされませんでした。
有効ではないスレッド間の操作:
コントロールが作成されたスレッド以外のスレッドからコントロール '' がアクセスされました。


みたいなエラーが出ます。

別スレッドから、コントロールを操作するには、
コントロールのInvokeを取得し、delegateにて操作します。
しかしToolStripProgressBarやToolStripStatusLabelに関しては、Invokeが取得できません。
よって、そのオーナを取得してInvokeを取得します。

色々試したので、下記にサンプルを書きます。
このサンプルは、カウンターを別スレッドで動かして、
TextBox, ToolStripProgressBar, ToolStripStatusLabelの値を変更しています。

invokesample1.jpg

Form1.cs


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 WindowsFormsApplication1 {
public partial class Form1 : Form {

// スレッドの作成
Thread _thread;
private delegate void SetValue(int val);

public Form1() {
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e) {
_thread = new Thread(new ThreadStart(formInvokeCounter));
_thread.Start();
}

private void button2_Click(object sender, EventArgs e) {
toolStripProgressBar1.Value = 0;
_thread = new Thread(new ThreadStart(controlInvokeCounter));
_thread.Start();
}

// このファンクションを別スレッドで動作させると、
// invokeしてないためエラーが発生します。
private void errorCounter() {
for (int i = 0; i <= 100; i++) {
textBox1.Text = i.ToString();
toolStripProgressBar1.Value = i;
toolStripStatusLabel1.Text = i.ToString();
Thread.Sleep(100);
}
}

// フォームまるごとInvokeします。
    // フォームのコントロールが取得できる場合に有効です。
private void formInvokeCounter() {
for (int i = 0; i <= 100; i++) {
this.Invoke(new SetValue(delegate(int val) {
textBox1.Text = val.ToString();
toolStripProgressBar1.Value = val;
toolStripStatusLabel1.Text = val.ToString();
}), i);

Thread.Sleep(100);
}
}

// コントロール毎Invokeします。
// フォームのコントロールが取得できない場合に有効です。
private void controlInvokeCounter() {
for (int i = 0; i <= 100; i++) {
textBox1.Invoke(new SetValue(delegate(int val) {
textBox1.Text = val.ToString();
}), i);
toolStripProgressBar1.ProgressBar.Invoke(new SetValue(delegate(int val) {
toolStripProgressBar1.Value = val;
}), i);
toolStripStatusLabel1.Owner.Invoke(new SetValue(delegate(int val) {
toolStripStatusLabel1.Text = val.ToString();
}), i);

Thread.Sleep(100);
}
}
}
}




ここでのポイントは、68行目の
toolStripStatusLabel1.Owner.Invoke(new SetValue(delegate(int val) {...

toolStripStatusLabelは、Invokeが取れないので、OwnerにてオーナーからInvokeを取得しています。
(toolStripProgressBarは、とれちゃいました(^_^;))


まとめると、
別スレッドからコントロールを操作したい場合は、コントロール、もしくは、
コントロールを持っているオーナーのInvokeを取得して操作する。



終わり。







スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

ss_9

名前 :ss_9
紹介 :
20代はエンジニア、30代はプロ、40代は管理、50代は人脈。

Twitterボタン

最新記事
カテゴリ
AD
月別アーカイブ
RSSリンクの表示
RSSリンクの表示
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。