Cześć.
Przy użyciu WCF stworzyłem serwis. Teraz usiłuje zaimplementować metodę, która zaktualizuje dane we wszystkich klientach poprzez wywołanie metody callback.
Serwis wystawia metodę, dzięki której klient "rejestruje się" w usłudze:
private static Dictionary<Guid, ICallbacks> clients = new Dictionary<Guid, ICallbacks>();
public void RegisterInService(Guid clientID)
{
ICallbacks callback = OperationContext.Current.GetCallbackChannel<ICallbacks>();
lock (clients)
{
if (!clients.ContainsKey(clientID))
{
clients.Add(clientID, callback);
}
}
}
public void UnregisterFromService(Guid clientID)
{
lock(clients)
{
if (clients.ContainsKey(clientID))
clients.Remove(clientID);
}
}
Opcje serwisu zostały zostały zdefiniowane w ten sposób:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
Serwis posiada również metodę, której zadaniem jest wykonanie bardziej złożonych operacji, a następnie wywołanie kolejnej metody, której zadaniem jest rozesłanie wyników do wszystkich "zarejestrowanych" klientów:
public void MainProcessActions()
{
SendMessageToAllClients("Roześlij do wszystkich");
}
private void SendMessageToAllClients(string data)
{
StreamWriter file = new System.IO.StreamWriter(@"E:\Temp\ClientsInvokingEvidence.txt", true);
lock (clients)
{
foreach (KeyValuePair<Guid, ICallbacks> client in clients)
{
client.Value.UpdateClientData(data);
file.WriteLine("Invoking method for client ID : {0}", client.Key);
}
}
file.Close();
}
Problem w tym, że metoda callback u klienta:
public interface ICallbacks
{
[OperationContract(IsOneWay = true)]
void UpdateClientData(string data);
}
, wywoływana jest tylko dla instancji aplikacji na rzecz której wywołana została metoda MainProcessActions(), a docelowo chciałbym aby została wywołana dla każdej uruchomionej instancji aplikacji. Co w teorii powinno być realizowane przez metodę SendMessageToAllClients() - dla każdego elementu słownika. Poszczególni klienci rejestrują się poprawnie w serwisie. Podczas wykonywania metody SendMessageToAllClients w słowniku istnieje tyle wpisów co uruchomionych aplikacji klienckich.
#edit
Okazuje się, że metoda callback jest jednak prawidłowo wywoływana dla każdego klienta... Problem leży zupełnie gdzie indziej. Otóż, dane otrzymane z serwisu używane są do ustawiania tekstu w kontrolce TextBox w Windows Forms. W klasie, w której implementuję metodę callback stworzyłem property, które jest ustawiane właśnie przez tą metodę. Następnie w klasie głównej formy używam instancji klasy z metodą callback aby ustawić tekst w kontrolce. Niestety, tak jak wspomniałem wcześniej tekst jest ustawiany tylko dla instancji klienta na rzecz którego zainicjalizowane zostało wywołanie metody MainProcessActtions() po stronie serwisu.
Czy nie ma to przypadkiem czegoś wspólnego z Synchronization Context?
Jeżeli do klasy, w której implementuje metodę callback przekażę referencję do obiektu kontrolki TextBox, wówczas jestem w stanie ustawić tekst dla każdego klienta równocześnie - tylko nie wiem czy jest to dobre rozwiązanie (jest to raczej sprzeczne z modelem View / Controler).
Macie jakiś pomysł?
Możecie mi dać jakąś wskazówkę, która naprowadzi mnie na rozwiązanie tego problemu?
Pozdrawiam