200 votes

Automatiser la configuration InvokeRequired

Je suis devenu douloureusement conscient de la façon dont souvent on a besoin d'écrire le code suivant modèle en event-driven code de la GUI, où

private void DoGUISwitch() {
    // cruisin for a bruisin' through exception city
    object1.Visible = true;
    object2.Visible = false;
}

devient:

private void DoGUISwitch() {
    if (object1.InvokeRequired) {
        object1.Invoke(new MethodInvoker(() => { DoGUISwitch(); }));
    } else {
        object1.Visible = true;
        object2.Visible = false;
    }
}

C'est un peu maladroite motif en C#, tant à retenir et à taper. A quelqu'un de venir avec une sorte de raccourci ou de la construction qui automatise ce à un degré? Ce serait cool si il y avait un moyen d'attacher une fonction à des objets qui n'cette case sans avoir à passer par tout ce travail supplémentaire, comme un object1.InvokeIfNecessary.visible = true type de raccourci.

Les précédentes réponses ont discuté de l'impossibilité de simplement appeler Invoke() à chaque fois, et même alors, la Invoke() la syntaxe est à la fois inefficace et toujours difficile à traiter.

Donc, quelqu'un a compris tous les raccourcis?

154voto

Lee approche peut être encore simplifié

public static void InvokeIfRequired(this Control control, MethodInvoker action)
{
    if (control.InvokeRequired) {
        control.Invoke(action);
    } else {
        action();
    }
}

Et peut être appelée comme ceci

richEditControl1.InvokeIfRequired(() =>
{
    // Do anything you want with the control here
    richEditControl1.RtfText = value;
    RtfHelpers.AddMissingStyles(richEditControl1);
});

Il n'est pas nécessaire de passer le contrôle en tant que paramètre pour le délégué. C# crée automatiquement une fermeture.


Mise à JOUR:

Selon plusieurs autres affiches Control peut être généralisée ISynchronizeInvoke:

public static void InvokeIfRequired(this ISynchronizeInvoke obj,
                                         MethodInvoker action)
{
    if (obj.InvokeRequired) {
        var args = new object[0];
        obj.Invoke(action, args);
    } else {
        action();
    }
}

DonBoitnott a souligné que, à moins d' Control le ISynchronizeInvoke interface nécessite un tableau d'objets pour l' Invoke méthode en paramètre de la liste de l' action.

138voto

Lee Points 63849

Vous pouvez écrire une méthode d’extension :

Et l’utiliser comme ceci :

EDIT : Comme le souligne Simpzon dans les commentaires vous pouvez également modifier la signature :

40voto

Matt Davis Points 22019

Voici la forme que je sers de tout mon code.

J’ai ceci basé sur l’entrée de blog ici. Je n’ai pas eu cette approche me manquent, donc je ne vois aucune raison de compliquer mon code avec un chèque de la `` propriété.

J’espère que cela aide.

10voto

Aaron Gage Points 1374

Créez un fichier ThreadSafeInvoke.snippet, et puis vous pouvez juste sélectionner les instructions update, clic droit et sélectionnez « Entourer de... » ou Ctrl-K + S :

6voto

stephan Schmuck Points 21

J’utiliserais plutôt une seule instance d’une délégué de méthode au lieu de créer une nouvelle instance chaque fois. Dans mon cas, j’ai utilisé pour afficher les messages (info/erreur) et d’avancement d’une Backroundworker copie et moulage de grandes données d’une instance de sql. Everywhile après environ 70000 progrès et message appelle mon formulaire cessé de travailler et affichage des nouveaux messages. Cela n’a pas occure lorsque j’ai commencé à utiliser un délégué unique instance globale.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X