У меня есть собственная WCF-служба с одноранговой привязкой. Я использую DuplexChannel для получения ответов. Сам обратный вызов работает. Я сохраняю обратные вызовы в статическом словаре. Когда клиент входит в систему, обратный вызов добавляется в словарь. Но когда я создаю несколько клиентов, статические переменные пусты.WCF: служба не работает для нескольких клиентов
Это моя служба интерфейса:
реализация[ServiceContract(SessionMode = SessionMode.Allowed, CallbackContract = typeof(ICallbackService))]
public interface IService
{
[OperationContract(IsOneWay = true)]
void Login(string email, string password);
[OperationContract(IsOneWay = true)]
void Logout(int userId);
}
Мои IService:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service : IService
{
private ServiceHost host = null;
private DuplexChannelFactory<IService> channelFactory = null;
private IService service = null;
private static Dictionary<ICallbackService, ICallbackService> pair = new Dictionary<ICallbackService, ICallbackService>();
private static Dictionary<string, ICallbackService> clients = new Dictionary<string, ICallbackService>();
private ICallbackService callback;
public Service(InstanceContext context)
{
startService(context);
}
private void startService(InstanceContext context)
{
host = new ServiceHost(this);
host.Open();
context.Open();
channelFactory = new DuplexChannelFactory<IBattleshipService>(context, "Endpoint");
channelFactory.Open();
service = channelFactory.CreateChannel();
callback = context.GetServiceInstance() as ICallbackService;
}
private void stopService()
{
if (host != null)
{
if (host.State == CommunicationState.Closed)
{
channelFactory.Close();
host.Close();
}
}
}
public void Login(string email, string password)
{
User user = getAllUsers().Find(u => u.Email.ToLower() == email.ToLower() && u.Password == password);
if (user != null)
{
Console.WriteLine("user : " + email + " has logged in");
clients.Add(email, callback);
callback.Authenticate(true);
}
else callback.Authenticate(false);
}
public void Logout(int userId)
{
string email = getUser(userId).Email;
clients.Remove(email);
stopService();
}
}
Мой обратный вызов службы:
public interface ICallbackService
{
[OperationContract(IsOneWay = true)]
void Authenticate(bool authenticated);
}
Исполнительное обратного вызова класса обслуживания в моем клиентском приложении:
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Single, UseSynchronizationContext = false)]
public class Client : Service.ICallbackService,
{
public bool Authentication { get; internal set; }
public Client()
{
}
public void Authenticate(bool authenticated)
{
Console.WriteLine("authentication : " + authenticated);
Authentication = authenticated;
}
}
1. Почему пара и клиенты являются статическими? –
Я хочу хранить всех клиентов и отправлять уведомления определенным пользователям –
Также вы должны использовать один из примитивов синхронизации для пары и клиентов, например lock. Или используйте поточный безопасный контейнер - ConcurrentDictionary –