tags:

views:

58

answers:

2

Hi folks,

in my C#-Silverlight-3-Application, I have created a class, that is doing some calculations that are used in different parts of my program. This class needs data from a database, so it calls a WCF-Service to get the data. The structure of the class looks like this:

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);
  }
}

The objects that need the calculation-class reference it and subscribe to the CalculationFinished event.

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
  }
}

I have more than one class like the IUseTheCalculation class that each have their own ConsumptionCalculation-Object.

My problem is the following: When I call the Do-method of the ConsumptionCalculation-object in one of the classes, ALL classes, that have a reference to any ConsumptionCalculation-object will receive the resulting CalculationFinished event. I think this is because all existing ConsuptionCalculation-objects recieve the dataSource_GetConsumtionInfoCompleted event from the WCF-Service. But I want only the calling object to receive the event. I guess there is a standard approach to this kind of problem, but I couldn't figure it out yet. How would you resolve this problem?

Thanks in advance, Frank

+1  A: 

You didn't show where or how you declare the CalculationFinished event. If it were static, that would explain the behavior you're seeing. But I'll assume you already checked that. Perhaps in the debugger you could examine the objects in question to determine if they are actually diffenent instances, as you are assuming they are.

Could you use the "id" field to distinguish the various callers (and if not, perhaps add an additional parameter to do so)? This wouldn't stop the other classes from getting notified, but they could all check quickly to see if the notification is for them, and return quickly if not.

Andy Jacobs
I added the declaration to the code above. All Calculation-Objects are initialized with the new-operator in the relevant classes' constructor. The id (or better the hashvalue, maybe?) to distinguish between the callers was the idea I had, but it feels more like a workaround and I wanted to see, if there is a more "best practice" approach ...
Aaginor
I agree that using the hash would be a work-around. But I haven't seen this issue before, and have seen it work properly, so you may not find a "best practice", since others may not be seeing it. So, if it's a bug, you may have to work around it.Before you give up, you can try looking with the debugger to confirm you are actually dealing with different instances of the objects - if not, you may be able to investigate to see what is going wrong (e.g., which objects are the same that you expected to be different, and look to see where they are declared, etc.).
Andy Jacobs
The issue was because I used a singleton object to access the WCF-Service. When each class that access the service gets its own Service-Client, everything works fine.
Aaginor
+1  A: 

What looks suspicious to me is:

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

How is DataContainer.instance.dataSource being told to associate that id with that ConsumptionCalculation instance? Is it being done in constructor like this?

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

Somehow there's a connection being made between DataContainer.instance and each instance of ConsumptionCalculation, and I bet you're connecting every single one to a single event.

Bryce Wagner
I wanted to have a single (Singleton) object to connect to / access the WCF-Service. After getting rid of that id and create an instance of the Service-Client for each class that needs to access the service, everything is working as expected.
Aaginor