2011-10-21 3 views
0

J'ai donc un problème intéressant (pour moi de toute façon). J'écris une application qui exécute une analyse et publie les informations d'une classe dans un Windows Form. Actuellement, je crée une instance d'un formulaire, en accédant à l'ActiveForm, puis en publiant du texte dans une fonction publique sous cette forme.Publication de texte d'événement de classe multithread à Windows ActiveForm

Scan.cs

// Sets the text of scan history in the ui 
private void SetScanHistory(string text) 
{ 
    MyWinForm1 form = (MyWinForm1)MyWinForm1.ActiveForm; 

    if (form != null) 
    { 
     form.SetText(text); 
    } 
} 

MyWinForm1.cs

// Sets the text of txtScanHistory to the text 
public void SetText(string text) 
{ 
    this.Invoke((MethodInvoker)delegate 
    { 
     // txtScanHistory is a TextBox 
     txtScanHistory.Text += text + Environment.NewLine; 
    }); 
} 

Alors maintenant, cela fonctionne assez bien. Le problème est lorsque l'utilisateur change de focus à partir du Windows Form le texte arrête de mettre à jour, ce qui explique pourquoi j'ai "if (form! = Null)". Je sais que ce n'est pas une façon idéale de faire ce que j'essaye de faire, alors ma question est comment puis-je changer ce code pour qu'il soit quelque chose comme un événement personnalisé dans "MyWinForm1"? Ou, s'il y a un autre moyen de le faire, j'aimerais voir des alternatives.

Répondre

1

Il y a deux manières de réaliser ce que vous voulez.

1) Vous pouvez ajouter une référence à la forme cible en tant que propriété de classe Scan.cs

public MyWinForm1 WinFormReference { get; set; } 

    // Sets the text of scan history in the ui 
    private void SetScanHistory(string text) 
    { 
     if (this.WinFormReference != null) 
     { 
      this.WinFormReference.SetText(text); 
     } 
    } 

vous pouvez passer la référence à votre classe d'analyse dans l'instance WinForm1 et définissez la propriété appropriée [ dans ce cas, je passe la classe du scanner à l'aide du constructeur WinForm]:

public void WinForm1(Scan scanner) 
    { 
     if (scanner != null) scanner.WinFormReference = this; 
    } 

2) Vous pouvez ajouter un événement personnalisé à la classe d'analyse puis accrochez le délégué à un rappel dans votre WinForm [nouveau, votre WinForm devra avoir une référence à votre classe d'analyse]:

public class SetScanHistoryEvents: EventArgs 
{ 
    public SetScanHistoryEvents(string text) 
    { 
     this.Text = text; 
    } 

    public string Text { get; set; } 
} 

public class Scan 
{ 
    public event EventHandler<SetScanHistoryEvents> ScanHistoryEvent; 

    // Sets the text of scan history in the ui 
    private void SetScanHistory(string text) 
    { 
     if (this.ScanHistoryEvent != null) 
     { 
      this.ScanHistoryEvent(this, new SetScanHistoryEvents(text)); 
     } 
    } 
} 

Ensuite, vous accrochez le rappel dans le constructeur de votre formulaire (ou ailleurs):

public MyWinForm1(Scan scanner) 
    { 
     if (scanner != null) 
      scanner.ScanHistoryEvent += new EventHandler<SetScanHistoryEvents>(scanner_ScanHistoryEvent); 
    } 

    private void scanner_ScanHistoryEvent(object sender, SetScanHistoryEvents e) 
    { 
     this.Invoke((MethodInvoker)delegate 
     { 
      // txtScanHistory is a TextBox 
      txtScanHistory.Text += text + Environment.NewLine; 
     }); 
    } 
0

Vous pouvez avoir quelque chose comme suivant qui utilisent SynchronizationContext

public partial class Form1 : Form 
    { 
     SynchronizationContext context; 
     public Form1() 
     { 
      InitializeComponent(); 
      context = SynchronizationContext.Current; 
     } 
     // Sets the text of scan history in the ui 
     private void SetScanHistory(string text) 
     { 
      CallFunc(text); 
     } 
     private void CallFunc(string TextValue) 
     {    
      context.Post(new SendOrPostCallback(
      delegate 
      { 
       textBox1.Text += TextValue + Environment.NewLine; 
      }), TextValue); 
     } 
    } 
+0

Je suis un peu confus. Dans mon exemple, SetScanHistory ne fait pas partie de la classe Form1. Aussi, si je devais faire ceci, comment pourrais-je faire pour définir le texte de ma classe "Scan" puisque toutes les fonctions sont privées? –

+0

Donc, j'ai fait un peu de lecture sur SynchronizationContext et je ne pense pas que ce soit ce que je cherche. Je n'ai aucun problème avec le threading pour le moment, le problème consiste à poster du texte d'une instance d'une classe dans un winform. Je ne sais pas si SynchronizationContext aide avec ceci, j'aimerais voir si cela peut. Mais en ce moment j'ai besoin d'aide pour la gestion des événements personnalisés. –

Questions connexes