2010-05-30 3 views

Répondre

4

La solution la plus simple est de capturer une variable locale dans une fermeture.

String text; 
textBox.Invoke(() => text = textBox.Text); 

Le compilateur génère un code qui est un peu comme la solution de chibacity - la variable locale devient un champ d'une classe généré par le compilateur.

MISE À JOUR

Cela ne fonctionne pas - l'expression lambda est incessible à Delegate. Ce problème peut être résolu en utilisant une méthode d'extension.

internal void ExecuteOnOwningThread(this Control control, Action action) 
{ 
    if (control.InvokeRequired) 
    { 
     control.Invoke(action); 
    } 
    else 
    { 
     action(); 
    } 
} 

L'utilisation est alors la suivante.

String text; 
textBox.ExecuteOnOwningThread(() => text = textBox.Text); 

Il est possible d'insérer plusieurs instructions dans l'expression lambda.

textBox.ExecuteOnOwningThread(() => 
{ 
    DoStuff(); 
    text = textBox.Text 
    DoOtherStuff(); 
}); 

Mais comme chibacity déjà mentionné dans un commentaire, il peut être préférable d'écrire explicitement une méthode. Au-delà d'un certain point, l'utilisation d'expressions lambda affectera la lisibilité du code. Et en utilisant des expressions lambda est bien sûr très enclin à introduire du code répété.

+0

Tout en ayant le one-liner est mignon, finalement vous allez faire plus que de fixer la variable par exemple dire à un autre fil, il y a des données prêtes. Avoir une méthode pour bourrer cela est la voie à suivre. –

+0

Je suis absolument d'accord avec vous - pour une, deux, ou peut-être trois déclarations qui ne sont pas répétées plusieurs fois, je considérerais utiliser une expression lambda mais au-delà, l'utilisation d'une méthode séparée donne le meilleur code. –

0

Vous pouvez transmettre un délégué à Invoke qui pointe vers une méthode qui peut définir une variable d'instance pour contenir la valeur de texte, par ex.

public Form1() 
    { 
     InitializeComponent(); 

     Invoke(new Action(SetTextboxTextVariable)); 
    } 

    private string _text; 

    private void SetTextboxTextVariable() 
    { 
     _text = txtBox.Text; 
    } 

Cela couvre l'idée de base, la synchronisation et la notification d'autres threads est à vous. :)

Mise à jour

Ou de le faire en une seule étape:

public Form1() 
    { 
     InitializeComponent(); 

     string text = GetText(); 
    } 

    private string GetText() 
    { 
     string text; 

     Invoke(new Action(text = txtBox.Text)); 

     return text; 
    } 
2

La méthode Control.Invoke() renvoie la valeur de la méthode appelée. Ce qui le rend facile:

 string value = (string)this.Invoke(new Func<string>(() => textBox1.Text)); 

Ou un peu plus explicite:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { 
     var dlg = new Func<string>(GetText); 
     string value = (string)this.Invoke(dlg); 
    } 
    private string GetText() { 
     return textBox1.Text; 
    } 
Questions connexes