サーチ…


他のスレッドからのフォームコントロールへのアクセス

テキストボックスやラベルなどのコントロールの属性を、コントロールを作成したGUIスレッド以外のスレッドから変更したい場合は、呼び出す必要があります。そうでない場合は、次のエラーメッセージが表示されることがあります。

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

このサンプルコードをsystem.windows.formsフォームで使用すると、そのメッセージで例外がキャストされます。

private void button4_Click(object sender, EventArgs e)
{
    Thread thread = new Thread(updatetextbox);
    thread.Start();
}

private void updatetextbox()
{
    textBox1.Text = "updated"; // Throws exception
}

テキストボックスのテキストを所有していないスレッド内から変更する場合は、Control.InvokeまたはControl.BeginInvokeを使用します。 Control.InvokeRequiredを使用して、コントロールを呼び出す必要があるかどうかを確認することもできます。

private void updatetextbox()
{
    if (textBox1.InvokeRequired)
        textBox1.BeginInvoke((Action)(() => textBox1.Text = "updated"));
    else
        textBox1.Text = "updated";
}

これを頻繁に行う必要がある場合は、このチェックを行うために必要なコードの量を減らすために、呼び出し可能なオブジェクトの拡張機能を記述することができます。

public static class Extensions
{
    public static void BeginInvokeIfRequired(this ISynchronizeInvoke obj, Action action)
    {
        if (obj.InvokeRequired)
            obj.BeginInvoke(action, new object[0]);
        else
            action();
    }
}

そして、どのスレッドからでもテキストボックスを更新するのは少しシンプルになります:

private void updatetextbox()
{
    textBox1.BeginInvokeIfRequired(() => textBox1.Text = "updated");
}

この例で使用されているControl.BeginInvokeは非同期であり、渡されたデリゲートがまだ実行されているかどうかにかかわらず、Control.BeginInvokeを呼び出した後のコードをimmedeately実行できることに注意してください。

続行する前にtextBox1が更新されていることを確認する必要がある場合は、代わりにControl.Invokeを使用して、代理人が実行されるまで呼び出しスレッドをブロックします。多くの呼び出しを呼び出し、GUIスレッドが呼び出しスレッドが保持されたリソースを完了または解放するのを待っている場合、アプリケーションのデッドロックが発生すると、このアプローチはコードを大幅に遅くする可能性があることに注意してください。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow