2009-08-23 9 views
1

J'ai cherché stackoverflow pour les moyens de marshaler des données d'un thread à l'UI thread, et ont trouvé diverses façons de le faire dans 3.5.J'ai besoin de définir plus d'une seule propriété pendant Control.Invoke

Une des solutions les plus élégantes pour moi; bien que j'apprenne encore lambdas et les fermetures est cette solution Control.Invoke with input Parameters.

Je ne comprends pas complètement le code, mais je comprends comment l'utiliser et cela ne résout pas tout à fait mon problème.

Je voudrais appeler invoquer et passer une chaîne à une autre méthode (DisplayStatusUpdate (msg)). Tout pointeur serait apprécié.

private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e) 
    { 
     DisplayStatusUpdate(e.LoggingEvent.RenderedMessage); 
    } 

    private void DisplayStatusUpdate(string text) 
    { 
     _StatusTextBox.Text = _StatusTextBox.Text + text; 
     _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text); 
     _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1; 
     _StatusTextBox.ScrollToCaret(); 
    } 

Répondre

5

Vous pouvez le faire avec autant de paramètres que vous le souhaitez, par exemple:

private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e) 
{ 
    DisplayStatusUpdate(e.LoggingEvent.RenderedMessage); 
} 

private delegate void DisplayStatusUpdateDelegate(string text); 

private void DisplayStatusUpdate(string text) 
{ 
    if(InvokeRequired) 
     this.Invoke(new DisplayStatusUpdateDelegate(DisplayStatusUpdate), text); 
    else 
    { 
     _StatusTextBox.Text = _StatusTextBox.Text + text; 
     _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text); 
     _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1; 
     _StatusTextBox.ScrollToCaret(); 
    } 
} 

Il y a une autre méthode que je l'ai utilisé dans un projet en cours qui peut réduct le code de manière significative. Les détails sont here.

Si vous implémentez cette méthode, vous devez:

Créer le formulaire en utilisant l'usine AOP:

Form f = AOPFactory.Create<Form1>(); 
Application.Run(f); 

Et puis vous décorer le gestionnaire d'événements avec l'attribut [RunInUIThread]. Il utilise le modèle d'interception de méthode de Castle pour invoquer automatiquement si nécessaire.

Ainsi, le code ci-dessus devient:

private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e) 
{ 
    _StatusTextBox.Text = _StatusTextBox.Text + text; 
    _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text); 
    _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1; 
    _StatusTextBox.ScrollToCaret(); 
} 

Performance sage, il semble être comparable, un peu plus lent, mais en fonction de ce que vous faites, il peut être correct, il faut certainement moins de code.

+0

Bien, merci Brandon. Je savais que la signature allait changer un peu pour DisplayStatusUpdate, mais ne pouvait tout simplement pas le clouer. –

+0

désolé, la signature est la même mais vous saviez ce que je voulais dire. –

2

Si vous utilisez C# 3.5 (ou version ultérieure), vous pouvez utiliser des variables capturées, ce qui peut simplifier le code:

private void DisplayStatusUpdate(string text) 
{ 
    this.Invoke(new MethodInvoker(() => 
    { 
     _StatusTextBox.Text = _StatusTextBox.Text + text; 
     _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text); 
     _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1; 
     _StatusTextBox.ScrollToCaret(); 
    })); 
} 

Ce que le compilateur fera dans les coulisses ici est de générer une classe pour tenir la text, créez un délégué MethodInvoker et transmettez ce délégué et une instance de la classe générée à la méthode Invoke. Dans la conception ci-dessus, cela va bien sûr faire le travail inutile de créer un délégué et d'appeler Invoke même si le code est déjà exécuté sur le même thread; mais je crois qu'une méthode comme celle-ci ne devrait pas être appelée si souvent que ce serait un problème de performance.

Si vous le souhaitez, vous pouvez remplacer l'utilisation de MethodInvoker par le délégué Action sans paramètre ou par tout autre délégué sans paramètre qui renvoie void.

+0

C'est génial! – Brandon