2010-02-03 4 views
2

Dans mon C# -Silverlight-3-Application, j'ai créé une classe, qui fait des calculs qui sont utilisés dans différentes parties de mon programme. Cette classe a besoin de données provenant d'une base de données, elle appelle donc un service WCF pour obtenir les données. La structure de la classe ressemble à ceci:Restreindre les événements asynchrones à l'objet appelant

public class ConsumptionCalculation 
{ 
    // Declare the event to notify subscribers, that the calculation has finished 
    public delegate void HandlerConsumtionCalculationFinished(object sender, ConsumtionCalculationArgs args); 
    public event HandlerConsumtionCalculationFinished CalculationFinished; 

    public void Do(int id) 
    { 
    // call the WCF-Service 
    DataContainer.instance.dataSource.GetConsumtionInfoAsync(id); 
    } 

    void dataSource_GetConsumtionInfoCompleted(object sender, GetConsumtionInfoCompletedEventArgs e) 
    { 
    // Receive the result of the WCF-Service call 
    // do some calculation here and put the results in the variable 'args' 

    // Raise an event to notify listeners, that the calculation is finished 
    CalculationFinished(this, args); 
    } 
} 

Les objets qui ont besoin de la référence calcul classe et abonnez-vous à l'événement CalculationFinished.

public class IUseTheCalculation 
{ 
    ConsumptionCalculation _calcObject; 

    public IUseTheCalculation() 
    { 
    _calcObject = new ConsumptionCalculation(); 
    _calcObject.CalculationFinished += new HandlerConsumptionCalculationFinished(CalculationFinishedEvent); 
    } 

    private void CalculationFinishedEvent(object sender, ConsumptionCalculationArgs args) 
    { 
    // use the calculation to display data or write it to a file or whatever 
    } 
} 

J'ai plus d'une classe comme la classe IUseTheCalculation qui ont chacun leur propre ConsumptionCalculation-objet.

Mon problème est le suivant: Lorsque j'appelle la méthode Do de l'objet ConsumptionCalculation dans l'une des classes, toutes les classes qui ont une référence à un objet ConsumptionCalculation recevront l'événement CalculationFinished résultant. Je pense que c'est parce que tous les objets ConsuptionCalculation existants reçoivent l'événement dataSource_GetConsumtionInfoCompleted du service WCF. Mais je veux seulement que l'objet appelant reçoive l'événement. Je suppose qu'il y a une approche standard à ce genre de problème, mais je ne pouvais pas encore le comprendre. Comment résoudriez-vous ce problème?

Merci à l'avance, Frank

+0

Une raison pour laquelle vous n'avez pas créé de proxy asynchrone, plutôt que de l'implémenter vous-même? –

+0

Je suis désolé, mais je ne comprends pas votre point. – Aaginor

Répondre

1

Vous ne l'avez pas montrer où ou comment vous déclarez l'événement CalculationFinished. Si c'était statique, cela expliquerait le comportement que vous voyez. Mais je suppose que vous avez déjà vérifié cela. Peut-être que dans le débogueur, vous pouvez examiner les objets en question pour déterminer s'ils sont réellement des instances différentes, comme vous le supposez.

Pourriez-vous utiliser le champ "id" pour distinguer les différents appelants (et sinon, peut-être ajouter un paramètre supplémentaire pour le faire)? Cela n'empêche pas les autres classes d'être notifiées, mais elles peuvent toutes vérifier rapidement si la notification est pour elles et revenir rapidement si ce n'est pas le cas.

+0

J'ai ajouté la déclaration au code ci-dessus. Tous les objets de calcul sont initialisés avec le nouvel opérateur dans le constructeur des classes concernées. L'id (ou mieux le hashvalue, peut-être?) Pour distinguer les appelants était l'idée que j'avais, mais ça ressemblait plus à une solution de contournement et je voulais voir, s'il y avait une approche plus "best practice" ... – Aaginor

+0

d'accord que l'utilisation du hachage serait une solution de rechange. Mais je n'ai jamais vu ce problème auparavant et je l'ai vu fonctionner correctement, de sorte que vous ne trouverez peut-être pas de «meilleure pratique», puisque d'autres ne le verront peut-être pas. Donc, si c'est un bug, vous devrez peut-être contourner ce problème. Avant d'abandonner, vous pouvez essayer de vérifier avec le débogueur que vous êtes en train de traiter différentes instances des objets. Dans le cas contraire, vous pourrez peut-être rechercher ce qui ne va pas (par ex., quels objets sont les mêmes que vous attendiez d'être différents, et regardez pour voir où ils sont déclarés, etc.). –

+0

Le problème était parce que j'ai utilisé un objet singleton pour accéder au service WCF. Lorsque chaque classe accédant au service obtient son propre Service-Client, tout fonctionne correctement. – Aaginor

1

Ce qui semble suspect pour moi est:

public void Do(int id) 
    { 
     // call the WCF-Service 
     DataContainer.instance.dataSource.GetConsumtionInfoAsync(id); 
    } 

Comment est DataContainer.instance.dataSource étant dit d'associer cet identifiant à cette instance de ConsumptionCalculation? Cela se fait-il dans un constructeur comme celui-ci?

public ConsumptionCalculation() 
{ 
    DataContainer.instance.dataSource.OnGetConsumptionInfoComplete += CalculationFinishedEvent; 
} 

D'une certaine façon, il y a une connexion entre DataContainer.instance réalisés et chaque instance de ConsumptionCalculation, et je parie que vous connectez chacun unique à un seul événement.

+0

Je voulais avoir un seul objet (Singleton) pour se connecter au service WCF. Après avoir supprimé cet ID et créé une instance du Service-Client pour chaque classe qui doit accéder au service, tout fonctionne comme prévu. – Aaginor

Questions connexes