В конце концов дуплексный клиент WCF Silverlight 4 начинает получать 404 Not Found
ошибки для сообщений опроса сразу после того, как опрос был отправлен из службы WCF клиенту Silverlight, иногда это происходит для второго опроса, иногда подключение работает часами или даже днями, но в основном не удается в первые минуты.
! И что интересно, проблема похожа на известную ошибку Silverlight 4 при использовании режима MaxMessagesPerPoll
duplex, и решение описано здесь и здесь, но я использую SingleMessagePerPoll
режим. В любом случае я пробовал использовать ClientStack
, как предлагалось, но ничего не изменилось.
Общий поток:
- Клиент SL выполняет метод службы WCF, получил ответ
- Затем немедленно клиент SL начинает отправлять сообщения опроса в службу, а затем получает исключение для второго или N-s сообщения опроса
# P4 #
- Fiddler показывает только пустой ответ
404
на сообщение опроса - Затем возникло событие "Ошибка канала клиента".
Я пытаюсь повторно подключить SL-клиент после такой ошибки, один поток повторных попыток повторного подключения:
- Обработка события
Faulted
- Отменить подписку на все события канала, такие как
Closed/Closing/Opened/Opening
- Правильно закройте канал, используя
try { close } catch { abort }
- Все ниже в новой ветке опроса: (Я обнаружил, что это работает немного стабильно - см. эту статью)
- Подождите 45-70 секунд
- Используя тот же экземпляр
DuplexChannelFactory<T>
, создайте новый канал, подпишитесь на все события канала только для целей регистрации - Выполнить метод службы WCF
После 1-10 попыток (~ 1-10 минут) клиент в конце концов подключается к серверу и продолжает нормальный опрос.
В журнале службы WCF я вижу, что он получает все запросы очистки, обрабатываемые без каких-либо исключений, поэтому кажется, что что-то происходит на стороне клиента Silverlight.
Главная информация:
- .NET Framework 4.0
- PollingDuplex
- Асинхронные методы WCF
- Служба WCF, размещенная в IIS 6.0
- Silverligth 4 клиент
- Клиентская ОС: Windows XP SP2
- Серверная ОС: Windows 2003 R2 SP2
- NTLM аутентификация
- DuplexMode: SingleMessagePerPoll
- Существует другая служба WCF, которая выполняет запрос / ответ до того, как моя служба начнет работать, она не использует дуплексное соединение.
- В клиентской службе SL я регистрирую все в пользовательском интерфейсе, чтобы видеть весь поток событий и иметь время для каждого конкретного события.
- Нет ошибок в журналах IIS, журналах событий сервера
Клиент:
var binaryBinding = new BinaryMessageEncodingBindingElement();
binaryBinding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
var httpbindingElement = new HttpTransportBindingElement
{
MaxReceivedMessageSize = 131072
};
var pollingDuplexBindingElement = new PollingDuplexBindingElement
{
ClientPollTimeout = new TimeSpan(0, 0, 1, 30),
InactivityTimeout = new TimeSpan(0, 8, 0, 0),
};
_binding = new CustomBinding(
pollingDuplexBindingElement,
binaryBinding,
httpbindingElement)
{
SendTimeout = new TimeSpan(0, 0, 0, 45),
CloseTimeout = new TimeSpan(0, 0, 0, 25),
ReceiveTimeout = new TimeSpan(0, 8, 0, 0),
OpenTimeout = new TimeSpan(0, 0, 0, 45)
};
httpbindingElement.AuthenticationScheme = AuthenticationSchemes.Negotiate;
var endpoint = new EndpointAddress(_endpointAddress);
_channelFactory = new DuplexChannelFactory<TWebService>(
new InstanceContext(instanceOfClientServiceClass),
_binding,
endpoint);
// then this factory used to create a new channels
// Also for a new channel I'm setting OpTimeout
var contextChannel = newChannel as IContextChannel;
if (contextChannel != null)
{
contextChannel.OperationTimeout = TimeSpan.FromSeconds(45);
}
Сервер:
- WCF, PerSession, многопоточный
- Все потокобезопасно
- Никаких исключений серверной службы во время выполнения
- Много журналов, поэтому я вижу, что происходит в сервисе
- Все трассировки WCF включены с помощью switchValue
All
, ничего подозрительного
<binding name="customName"
sendTimeout="00:01:00"
receiveTimeout="08:00:00"
openTimeout="00:01:00"
closeTimeout="00:00:35">
<pollingDuplex
inactivityTimeout="08:00:00"
serverPollTimeout="00:01:00" />
<binaryMessageEncoding />
<httpTransport authenticationScheme="Ntlm"
maxReceivedMessageSize="131072">
</httpTransport>
</binding>
<behavior name="customBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling
maxConcurrentCalls = "500"
maxConcurrentSessions = "500"
maxConcurrentInstances = "500" />
</behavior>