2010-05-05 7 views
2

J'essaie de désactiver des parties de l'interface utilisateur dans une application .NET basée sur l'interrogation effectuée sur un thread d'arrière-plan. Le thread d'arrière-plan vérifie si la connexion de base de données globale utilisée par l'application est toujours ouverte et opérationnelle. Ce que je dois faire, et que je préférerais faire sans interroger sur le thread de l'interface utilisateur, est d'ajouter un gestionnaire d'événements qui peut être levé par le thread d'arrière-plan si l'état de la connexion change. De cette façon, n'importe quel formulaire peut avoir un gestionnaire qui désactivera les parties de l'interface utilisateur qui nécessitent la connexion pour fonctionner. Tentative d'utilisation d'une déclaration d'événement rectiligne dans la classe contenant le sous-thread et augmentation de l'événement dans le thread d'arrière-plan entraînant des erreurs d'exécution croisées concernant l'accès aux contrôles d'interface utilisateur à partir d'autres threads.Délégués multithread/événements

De toute évidence, il existe une façon correcte de le faire, mais nous avons une expérience limitée avec les événements (applications à fil unique principalement), et presque aucun avec les délégués. J'ai lu la documentation et les exemples pour les délégués, et cela semble être plus proche de ce dont nous avons besoin, mais je ne sais pas comment le faire fonctionner dans ce cas.

L'application est écrite principalement dans VB.NET, mais un exemple ou une aide en C# est également bien.

+0

Dans dotNET, vous ne devriez pas avoir une connexion globale ouverte en permanence. Lisez sur ConnectionPooling. http://stackoverflow.com/questions/2715714/ –

+0

@Henk Holterman: Vous ne pouvez pas faire cette déclaration si vous ne connaissez pas ses circonstances. En outre, il n'est pas recommandé avec les fournisseurs que Microsoft inclut dans le cadre. – AMissico

+0

@AMissico: En utilisant ma technique ci-dessous, ça n'a pas d'importance (ça marche aussi bien pour les deux ...) –

Répondre

2

Vous pouvez rassembler la levée de l'événement en arrière sur le thread d'interface utilisateur. Comme cela est probable (si vous avez bien conçu) à partir d'une classe séparée, ma recommandation serait de passer une copie du SynchronizationContext courant dans votre classe qui gère le processus d'arrière-plan.

Voici quelques exemples de code en C#:

public class BackgroundWork 
{ 
    public SynchronizationContext Context { get; private set; } 
    public BackgroundWork(SynchronizationContext context) 
    { 
     this.Context = context; 
    } 

    // Thread handler, etc... 

    // Method to raise event 
    void RaiseEvent() 
    { 
     Context.Post((state) => 
     { 
      // Raise the event 
      this.ConnectionStatusChanged(this, EventArgs.Empty); 
     }, null); 
    } 
} 

Ensuite, lorsque vous construisez la classe (dans votre thread d'interface utilisateur), le passer, le contexte actuel:

BackgroundWork worker = new BackgroundWork(SynchronizationContext.Current); // This passes the UI thread context... 
worker.Start(); 

(Ce, par le manière, est la même technique que la classe BackgroundWorker utilise, ce qui explique pourquoi il fonctionne à la fois pour Windows Forms et WPF ...)

0

Vous résoudre l'erreur d'exécution de fil cross en utilisant Control.Dispatcher.Invoke:

public void EnventHandlerMethod(object sender, EventArgs e) 
{ 
    myLabel.Dispatch.Invoke(new Action(() => { myLabel.Content = "Updated"; })); 
} 

La signature du gestionnaire d'événements peut varier en fonction de l'événement que vous manipuler. Bien sûr, si vous changez simplement le contrôle dans un autre thread, vous n'avez besoin que du corps de la méthode ci-dessus.

Aussi cela (je pense) suppose .NET 3.5

+0

Cela résout le problème du côté de l'abonnement client, mais pas du côté de la connexion ... –

0

Essayez la méthode Invoke du contrôle que vous souhaitez modifier, ou tout contrôle vraiment, et une petite fonction fournissent à faire le travail que vous voulez. Ou voyez BeginInvoke pour le faire de manière asynchrone.

Faites juste attention sur les problèmes de filetage, modifier des variables du fil « principal » est en train de modifier, etc.

+0

Ceci (presque) résout le problème le côté de l'abonnement client, mais pas du côté de la mise en pool des connexions ... –