Recherche…


Accéder aux contrôles de formulaire à partir d'autres threads

Si vous souhaitez modifier un attribut d'un contrôle tel qu'une zone de texte ou une étiquette d'un autre thread que le thread d'interface graphique qui a créé le contrôle, vous devrez l'appeler ou vous pourriez recevoir un message d'erreur indiquant:

"L'opération inter-thread n'est pas valide: contrôlez 'nom_contrôle' à partir d'un thread autre que celui sur lequel il a été créé."

Utiliser cet exemple de code sur un formulaire system.windows.forms convertira une exception avec ce message:

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

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

Au lieu de cela, lorsque vous souhaitez modifier le texte d'une zone de texte à partir d'un thread qui ne lui appartient pas, utilisez Control.Invoke ou Control.BeginInvoke. Vous pouvez également utiliser Control.InvokeRequired pour vérifier si l'appel du contrôle est nécessaire.

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

Si vous devez le faire souvent, vous pouvez écrire une extension pour les objets invocables afin de réduire la quantité de code nécessaire pour effectuer cette vérification:

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

Et la mise à jour de la zone de texte à partir de n'importe quel thread devient un peu plus simple:

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

Sachez que Control.BeginInvoke tel qu'utilisé dans cet exemple est asynchrone, ce qui signifie que le code venant après un appel à Control.BeginInvoke peut être exécuté immédiatement après, que le délégué passé ait été exécuté ou non.

Si vous devez être sûr que textBox1 est mis à jour avant de continuer, utilisez plutôt Control.Invoke, qui bloquera le thread d'appel jusqu'à ce que votre délégué ait été exécuté. Notez que cette approche peut considérablement ralentir votre code si vous lancez de nombreux appels et notez qu'il bloquera votre application si votre thread d'interface graphique attend que le thread appelant termine ou libère une ressource en attente.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow