WCF дуплексные обратные вызовы nettcp не работают
Среда
Служба WCF (NET:TCP | Reliable | SecurityEnabled) работает как консоль на физической машине A
Через Citrix открыто 20-30 клиентских приложений.NET (Winforms), поэтому они снова размещаются на одной физической машине, отличной от сервера.
проблема
Структура приложения следует той же схеме, которая обсуждалась Джувалом Лоуи в http://msdn.microsoft.com/en-us/magazine/cc163537.aspx.
Проблема в том, что на сервере он может вызвать обратный вызов без ошибок, но клиент никогда его не получает. Существует код пытается подписаться снова, если нет обратного вызова в течение 60 секунд. У него есть побочный эффект, что он открывает новое соединение, вызывая API подписки на сервере. В течение определенного периода вы можете увидеть множество TCP-соединений, открытых на сервере. Нет ошибок, но все равно клиентский обратный вызов никогда не вызывается.
Дополнительная информация
Иногда выдается следующая ошибка:
Сообщение не может быть передано в течение установленного времени ожидания 00:01:00. В окне передачи надежного канала не было свободного места. Время, выделенное для этой операции, могло быть частью более длительного времени ожидания.
Кроме того, MaxBufferPoolSize имеет значение Int64.MaxValue, как вы можете видеть в коде ниже
var binding = new NetTcpBinding(SecurityMode.Transport, reliableSession);
binding.ReliableSession.Enabled = true;
binding.ReliableSession.InactivityTimeout = TimeSpan.FromDays(1);
binding.ReliableSession.Ordered = true;
binding.CloseTimeout = TimeSpan.FromHours(1);
binding.SendTimeout = TimeSpan.FromHours(1);
binding.ReceiveTimeout = TimeSpan.FromHours(1);
binding.OpenTimeout = TimeSpan.FromHours(1);
binding.ReaderQuotas.MaxDepth = Int32.MaxValue;
binding.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
binding.ReaderQuotas.MaxArrayLength = Int32.MaxValue;
binding.ReaderQuotas.MaxBytesPerRead = Int32.MaxValue;
binding.ReaderQuotas.MaxNameTableCharCount = Int32.MaxValue;
binding.MaxBufferPoolSize = Int64.MaxValue;
binding.MaxReceivedMessageSize = Int32.MaxValue;
Любые предложения будут отличной помощью!
2 ответа
Недавние выводы:
Я недавно обнаружил, что обратный вызов на стороне клиента имеет различные виды обработки в зависимости от того, что видно на экране пользователя. Это блокировало обратные вызовы для подтверждения. Это также объясняет переполнение буфера. Частота уведомлений, отправляемых с сервера, очень высока по сравнению со временем, затрачиваемым каждым клиентом на их обработку.
Помимо изменений, которые мне нравились: отключение безопасности, правильная настройка таймаутов, мне очень помогла следующая строка кода:
public void OnNotification(AmigoMessage messsage)
{
ThreadPool.QueueUserWorkItem((x) => { ProcessNotification(messsage); });
}
Взгляни на [CallbackBehavior(UseSynchronizationContext = false)]
, Отсутствие этого атрибута в службе обратного вызова попытается выполнить маршалирование (обычно) потока пользовательского интерфейса.