I have a WAS service configured on Windows 10 IIS 1511. I created a simple test app to get all major problem areas sorted before I start with my actuall project. I have my service configured with concurrency multiple and Instance to single. I have a concurrent dictionary to manage the concurrency. I do 2 calls to the service with 2 different proxy objects to subscribe to my observer/subject. the subscribe method adds subscribers to the dictionary. after the second proxy call there are only one item in the dictionary and I was expecting 2. So it seems my service is not persisting my changes to the dictionary. However if I use the Hello operation, which just increase a counter (value type) then the count is 2 after second call. Here is my client console code:
static void Main(string[] args)
{
string personErnie = "Ernie";
string personAlvin = "James";
//using (PersonTracker.PersonTrackerClient personTracker1 =
// new PersonTracker.PersonTrackerClient("PersonTrackerPipeEndPoint"))
//using (PersonTracker.PersonTrackerClient personTracker2 =
// new PersonTracker.PersonTrackerClient("PersonTrackerPipeEndPoint"))
using (PersonTracker.PersonTrackerClient personTracker1 =
new PersonTracker.PersonTrackerClient("PersonTrackerHTTPEndPoint"))
using (PersonTracker.PersonTrackerClient personTracker2 =
new PersonTracker.PersonTrackerClient("PersonTrackerHTTPEndPoint"))
{
string h1 = personTracker1.Hello(personErnie); //Output: Hello Ernie, Seems like you using the http protocol, count = 1
string h2 = personTracker1.Hello(personAlvin); //Output: Hello James, Seems like you using the http protocol, count = 2
PersonObserver personObserverErnie = new PersonObserver(personErnie);
object disposeObserverErnie = personTracker1.Subscribe(personObserverErnie); // Dictionary Count = 1
PersonObserver personObserverJames = new PersonObserver(personAlvin);
object disposeObserverJames = personTracker2.Subscribe(personObserverJames); // Dictionary Count = 1
}
}
Here is my service class:
[ServiceBehavior(
ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode =InstanceContextMode.Single)]
public class PersonTracker : IPersonTracker
{
public static ConcurrentDictionary<string, PersonObserver> observers = null;
int Counter;
public string Hello(string name)
{
string protocol = OperationContext.Current.Channel.LocalAddress.Uri.Scheme;
return string.Format("Hello {0}, Seems like you using the {1} protocol, count = {2}",name, protocol,Counter++);
}
public UnsibscribePerson Subscribe(PersonObserver observer)
{
if (observers == null)
{
observers = new ConcurrentDictionary<string, PersonObserver>();
}
if (!observers.ContainsKey(observer.Name))
{
observers.AddOrUpdate(observer.Name, observer, (key, oldValue) => { return new PersonObserver(oldValue.Name); });
}
return new UnsibscribePerson(observers, observer);
}
}
Here is my Contract interface:
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IPersonTracker
{
[OperationContract]
string Hello(string name);
[OperationContract]
UnsibscribePerson Subscribe(PersonObserver observer);
}
The unsubscribe class is a class extending the IDisposable for the client to de-register itself once I have remoting (Pipes) sorted.
Question: Why does the dictionary not persist my observers i add but for the counter it does...
UPDATE:
So just by removing the UnsibscribePerson object in the return type of my Subscribe operation I have my issue resolved, however I need to return this object. Is this something to do with my UnsibscribePerson object, here is my changes made and my UnsibscribePerson object:
[ServiceContract]
public interface IPersonTracker
{
[OperationContract]
string Hello(string name);
[OperationContract(IsInitiating = true)]
void Subscribe(PersonObserver observer);
}
And here is my UnsibscribePerson object:
[DataContract(IsReference = true)]
public class UnsibscribePerson : IDisposable
{
[DataMember(EmitDefaultValue = false)]
private PersonObserver observer;
[DataMember(EmitDefaultValue = false)]
private ConcurrentDictionary<string, PersonObserver> persons;
public UnsibscribePerson(ConcurrentDictionary<string, PersonObserver> persons, PersonObserver observer)
{
this.persons = persons;
this.observer = observer;
}
public void Dispose()
{
if (observer != null && persons.ContainsKey(observer.Name))
{
PersonObserver person = null;
persons.TryRemove(observer.Name, out person);
}
}
}
I also change the return type to a value type (returning the count of the list) and I got the results (count of 1 and 2). This still seem to be related to reference types and value types?
This is embarrassing :) My dispose method on UnsibscribePerson class gets called which removes my subscriber right after it was added....
So solution for me was to not implement IDisposbale interface