2009-07-09 7 views
0

Je travaille sur la création d'un contrôle de thread thread pour mon application de formulaires Windows.Thread Safe Control - Crashing VS 2008

Je comprends que je peux mettre le texte sur un fil de contrôle en toute sécurité en utilisant le code suivant:

private delegate void SetTextD(Control control, string value); 

private static void SetText(Control control, string value) 
{ 
    if(control.InvokeRequired) 
    { 
     control.Invoke(new SetTextD(SetText), new object[] {control, value}); 
    } 
    else 
    { 
     control.Text = value; 
    } 
} 

Puis dans mon code de forme que je peux appeler:

SetText(lblStatus, "Updating..."); 

Mon but est de créer un contrôle personnalisé, qui hérite de Label. Ensuite, à l'intérieur de cette classe, sur la propriété Text je peux appeler:

lblStatus.Text = « Mise à jour ... »

Ensuite, il fera automatiquement le bon fil du code de sécurité.

Voici le code que j'ai dans ma classe:

public class ThreadSafeLabel : Label 
{ 
    private delegate string GetTextD(); 
    private delegate void SetTextD(string value); 

    private string GetText() 
    { 
     if (InvokeRequired) 
     { 
      return (string)Invoke(new GetTextD(GetText)); 
     } 
     return Text; 
    } 

    private void SetText(string value) 
    { 
     if(InvokeRequired) 
     { 
      Invoke(new SetTextD(SetText), new object[] {value}); 
     } 
     else 
     { 
      Text = value; 
     } 
    } 

    public override string Text 
    { 
     get 
     { 
      return GetText(); 
     } 
     set 
     { 
      SetText(value); 
     } 
    } 
} 

Maintenant, lorsque je tente d'ajouter ce contrôle à ma forme, il se bloque VS 2008. Je pensais que peut-être il fallait faire avec définir la propriété de texte initiale lorsque vous l'ajoutez au formulaire, mais pas sûr.

Des pensées sur ce que je pourrais faire de mal ou ce que je pourrais manquer?

Si quelque chose n'est pas clair, demandez.

Merci!

+1

Quelle exception obtenez-vous? – Clyde

+0

A 'StackOverflowException'. – SLaks

+0

.NET Runtime version 2.0.50727.3053 - Erreur de moteur d'exécution fatale (7A2E0F92) (0) – CodeLikeBeaker

Répondre

1

En raison des méthodes anonymes de C# 3.0, vous n'avez pas besoin de méthodes set et get séparées. La façon la plus simple de faire ce que vous cherchez est comme ceci:

public class ThreadSafeLabel : Label { 
    public override string Text { 
     get { 
      return InvokeRequired ? Invoke(new Func<string>(() => base.Text)) : base.Text; 
     } 
     set { 
      if (InvokeRequired) 
       BeginInvoke(new Action(() => base.Text = value)); 
      else 
       base.Text = value; 
     } 
} 

Notez que j'utilise BeginInvoke pour que le thread appelant n'attendra pas l'Invoke pour terminer; vous voudrez peut-être le changer en Invoke.

EDIT:

Le problème avec votre code est que votre jeu et obtenir des méthodes appellent votre substitution Text propriété à nouveau, créant ainsi une boucle infinte qui se traduit par un overlow de pile (l'exception, pas le site) . Vous devez écrire base.Text pour appeler l'implémentation de la classe de base de la propriété Text.

+1

Oui, le point est d'utiliser base.Text ... après cela, il peut refactor le code pour fonctionner sans délégués. – tanascius

+0

Voici ce que c'était. Merci pour l'info. – CodeLikeBeaker

2

Essayez un

return base.Text; 

ou vous courrez dans une boucle sans fin (lorsque vous ajoutez l'étiquette à votre formulaire Text-propriété est interrogé - et la boucle sans fin fait plantage VS). Pareil pour ton setter.