Ответ 1
Я пошел с подходом Abort. Это казалось самым логичным методом, и он работает очень хорошо. Клиент получает уведомление с Faulted-событием в контексте callback-instancecontext.
У меня есть собственная служба WCF с net.tcp DuplexChannel. На сервере я запускаю следующее, чтобы отключить клиент:
((ICommunicationObject)client.CallbackChannel).Close();
Это прекрасно работает, но как обнаружить на клиенте, что он был отключен?
Ive подключился к Closed и Faulted-событиям как в экземпляре Context для обратного вызова, так и для канала на сервер:
InstanceContext callback = new InstanceContext(callbackImp);
callback.Closed += new EventHandler(callback_Closed);
и
((ICommunicationObject)Channel).Closed += new EventHandler(Channel_Closed);
Но ничего не работает. Я никогда не получаю уведомление. Обходной путь Im, используемый сейчас, заключается в том, чтобы иметь метод в обратном вызове, который вместо этого отключает соединение с клиентской стороны. Но я предпочитаю не делать этого таким образом. Я особенно не хочу, чтобы сервер ожидал отключения пользователя.
ИЗМЕНИТЬ
Я только понял, что при отключении от клиентской стороны я запускаю метод в сервисе-контракте, который помечен IsTerminating = true:
[OperationContract(IsTerminating = true)]
void Disconnect();
Я полагал, что тогда будет так же в callback-контракте? Я попытался добавить тот же метод к моему обратному вызову, и он прекратил обратный канал с точки зрения сервера, но я все еще не получил уведомление на стороне клиента... странный
ИЗМЕНИТЬ
Я узнал дополнительную информацию об этом:
Когда сервер прерывает обратный вызов канал, ошибка возвращается к клиент, ошибки клиента, и мы получаем событие Faulted на клиенте.
Когда сервер закрывает обратный вызов канал, сеанс все еще открыт пока клиент не закрыт.
Как только клиент закрывает канал вы увидите закрытое событие.
В соответствии с этим утверждением Close-событие не запускается mearly, закрывая callbackchannel с сервера, клиент должен также закрыть его. Поэтому я мог запустить Close на клиенте в завершающем Disconnect-методе обратного вызова. Или я мог бы использовать метод Abort на стороне обратного вызова и пропустить с помощью метода Disconnect для обратного вызова. Я не знаю, какой из них я предпочитаю честно. Хммм.
ИЗМЕНИТЬ
Я пошел с подходом Abort. Это казалось самым логичным методом, и он работает очень хорошо. Клиент получает уведомление с Faulted-событием в callback-instancecontext. Ницца.
Я пошел с подходом Abort. Это казалось самым логичным методом, и он работает очень хорошо. Клиент получает уведомление с Faulted-событием в контексте callback-instancecontext.
Вы можете просто выполнить обратный вызов непосредственно перед закрытием канала обратного вызова, сообщающего клиенту, что вы закрываете канал.
Итак, перед этой строкой кода:
((ICommunicationObject)client.CallbackChannel).Close();