○ スレッドからコントロールの操作


.NET Framework version 2.0 からは、メインスレッド以外から、コントロールの操作ができないようです。
そのため、デリゲートを使いメインスレッドにコントロールの操作を行ってもらいます。

ワーカースレッドがメインスレッドに関数の処理を予約し実行してもらうイメージです。
メインスレッドからなら、コントロールにアクセスできます。



//-----------------------------------------------------------------
private void hoge()//fuga関数
{
    label1.Text = "aaa";
}
delegate void hoge_Delegate();//hoge関数のデリゲートを準備
//-----------------------------------------------------------------
private void piyo(String str)//piyo関数
{
    label1.Text = str;
}
delegate void piyo_Delegate(String str);//piyo関数のデリゲートを準備
//-----------------------------------------------------------------
private string fuga()//fuga関数
{
    return textBox1.Text ;
}
delegate String fuga_Delegate();//fuga関数のデリゲートを準備
//-----------------------------------------------------------------

private void thread_func()//スレッドを立てる関数
{
    while (true)
    {
        Invoke(new hoge_Delegate(hoge));//デリゲートを使いhoge関数をメインスレッドに実行してもらう
        System.Threading.Thread.Sleep(500);
        String str = (String)Invoke(new fuga_Delegate(fuga));//デリゲートを使いfuga関数をメインスレッドに実行してもらう
        Invoke(new piyo_Delegate(piyo), new object[] { str });//デリゲートを使いpiyo関数をメインスレッドに実行してもらう
        System.Threading.Thread.Sleep(500);
    }
}

private void thread_start()
{
    System.Threading.Thread th = new System.Threading.Thread(new System.Threading.ThreadStart(this.thread_func));
    th.Start();
}



■ 関数を作成しなくてもコントロールの関数は、デリゲートでスレッドから呼び出せます

下のプログラムでは、デリゲートで this.Controls.Add を呼び出してフォームにボタンを追加しています。


//ワーカースレッドとメインスレッドからフォームにボタンを追加する
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        System.Threading.Thread th = new System.Threading.Thread(new System.Threading.ThreadStart(this.hoge));
        th.Start();
        hoge();
    }

    delegate void test_Delegate(Control obj);
    
    private void hoge()
    {
        if (InvokeRequired)
        {
            //メインスレッド以外から呼ばれた場合
            Button obj = new Button();
            obj.Location = new System.Drawing.Point(0, 0);
            obj.Text = "ワーカースレッド";
            Invoke(new test_Delegate(this.Controls.Add), new object[] { obj });
        }
        else
        {
            //メインスレッドから呼ばれた場合
            Button obj = new Button();
            obj.Location = new System.Drawing.Point(50, 50);
            obj.Text = "メインスレッド";
            this.Controls.Add(obj);
        }
    }
}


▲トップページ > Visual BASIC と C#