Проверьте состояние клиента перед вызовом метода обратного вызова в WCF
У меня есть служба WCF и клиент WCF, работающий по дуплексному каналу с использованием netTCPBinding.
Я храню подключенных пользователей в словаре (Dictionary<int userID,CallbackInstance instance>
)
Когда пользователь регулярно отключается, звоните в службу "Отключить от службы", и я удаляю пользователя из списка подключенных пользователей. Работает нормально.
но когда клиентский компьютер отключается нерегулярно, клиент не может вызвать метод Disconnect, поэтому клиент все еще находится в списке подключенных пользователей, в этом проблема. Потому что, когда мой сервер WCF проверяет сервер для онлайн-пользователей на предмет обратного вызова, сервер пытается вызвать метод обратного вызова клиента, но клиент недоступен, и мое приложение WCF Server вылетает.
Можно ли проверить состояние клиента перед вызовом экземпляра обратного вызова?
2 ответа
Убедитесь, что для всех свойств установлены тайм-ауты для автоматического удаления неактивных клиентов, а затем перехватите исключение тайм-аута в блоке try catch и удалите его из своего словаря.
Я исправляю это с помощью:
1. Способ пинговать с клиента на сервер, чтобы поддерживать соединение активным каждые 30 секунд.
2. На привязке к серверу ReceiveTimeout с 1 минутой.
3. Для обратного вызова был создан объект IcommunicationObject, использующий событие Closed для удаления неактивного клиента.
//Adding a client callback
OperationContext context = OperationContext.Current;
ICallback callback = context.GetCallbackChannel();
ICommunicationObject obj = (ICommunicationObject)callback;
obj.Closed += new EventHandler(obj_Closed);
//Event for inactive clients
void obj_Closed(object sender, EventArgs e)
{
if (_callbacks.ContainsValue(((ITecnobelRemoteServiceCallback)sender)))
{
var item = _callbacks.First(kvp => kvp.Value == ((ITecnobelRemoteServiceCallback)sender));
_callbacks.Remove(item.Key);
treeViewClients.Nodes.RemoveByKey(item.Key.Id);
treeViewClients.Refresh();
_registeredUsers--;
listBoxStatus.Items.Add(String.Format("Usuário {0} estava inativo e foi removido", item.Key.Id));
}
}