Тайм-аут асинхронных вызовов WCF на стороне клиента через 10 секунд - PullRequest
6 голосов
/ 17 сентября 2010

РЕДАКТИРОВАТЬ

Посмотрев на это некоторое время, я подумал, что это может быть проблема с конфигурацией в моей коробке разработки.Тем не менее, после чистой загрузки исходного кода на другой компьютер для разработки, я все еще получаю эту проблему.

У меня есть клиент Silverlight, который асинхронно вызывает службы WCF.Периодически я получу одно из общих NotFound исключений.Исключения (которые, как известно, не содержат подробностей) периодически возникают практически во всех службах, которые я вызываю.

Вот в чем дело.При разумной установке точек останова я смог определить, что сервисная сторона работает нормально.Данные извлекаются и возвращаются.Проблема, кажется, больше на стороне клиента вещей.

Вот в чем дело ... Я могу последовательно сделать исключение, если я заставлю службу выполняться более 10 секунд.Когда я это делаю, он никогда не возвращается к моему завершенному обратному вызову.Вместо этого я получаю исключение в файле Reference.cs на стороне клиента для службы:

        public System.Collections.ObjectModel.ObservableCollection<Project.Ui.SilverLight.ServiceName.ModelName> EndGetService(System.IAsyncResult result) {
            object[] _args = new object[0];
            System.Collections.ObjectModel.ObservableCollection<roject.Ui.SilverLight.ServiceName.ModelName> _result = ((System.Collections.ObjectModel.ObservableCollection<roject.Ui.SilverLight.ServiceName.ModelName>)(base.EndInvoke("GetService", _args, result)));
            return _result;
        }

Полученное исключение (не очень полезно):

System.ServiceModel.CommunicationException was unhandled by user code
  Message=The remote server returned an error: NotFound.
  StackTrace:
       at System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result)
       at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
       at System.ServiceModel.ClientBase`1.ChannelBase`1.EndInvoke(String methodName, Object[] args, IAsyncResult result)
       at Project.Ui.SilverLight.Service.ServicesClient.ServicesClientChannel.EndGetxxxxx(IAsyncResult result)
       at Project.Ui.SilverLight.Service.ServicesClient.Project.Ui.SilverLight.Service.IServices.EndGetxxxx(IAsyncResult result)
       at Project.Ui.SilverLight.Service.ServicesClient.OnEndGet(IAsyncResult result)
       at System.ServiceModel.ClientBase`1.OnAsyncCallCompleted(IAsyncResult result)
  InnerException: System.Net.WebException
       Message=The remote server returned an error: NotFound.
       StackTrace:
            at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
            at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
            at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
       InnerException: System.Net.WebException
            Message=The remote server returned an error: NotFound.
            StackTrace:
                 at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
                 at System.Net.Browser.BrowserHttpWebRequest.<>c__DisplayClass5.<EndGetResponse>b__4(Object sendState)
                 at System.Net.Browser.AsyncHelper.<>c__DisplayClass2.<BeginOnUI>b__0(Object sendState)
            InnerException: 

Информация о привязке (имена изменились, но они соответствуют выполняемым службам)

    <binding name="Project.WebUI.Services.xxxxxServices.customBinding0" closeTimeout="00:01:00"
      openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00">
      <binaryMessageEncoding/>
      <httpTransport />
    </binding>

...

  <service name="Project.WebUI.Services.xxxxxServices">
    <endpoint address="" binding="customBinding" bindingConfiguration="Project.WebUI.Services.xxxxxServices.customBinding0"
      contract="Project.WebUI.Services.xxxxxServices" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>

Я считаю, что проверил соответствующие таймауты.Канал operationTimeout установлен как минимум на одну минуту, как и ReceiveTimeout и OpenTimeout.Есть ли что-то непонятное в Silverlight асинхронных вызовах WCF, которое нужно настроить, чтобы оно длилось более десяти секунд?

Ответы [ 5 ]

4 голосов
/ 04 октября 2010

Причина, по которой вас не нашли, это НЕ из-за тайм-аута. Я потерял неделю, пытаясь понять это.

У меня есть ссылки на silverlight, но это не специфическая проблема для silverlight.

Не найденная ошибка существует из-за способа создания кодов ошибок. Вам необходимо перехватить любые ошибки и изменить код ошибки - это приведет к тому, что ошибки будут сообщаться должным образом и не исчезать из-за безопасности.

Если вы подумаете об этом, сервер не найден, поскольку вызов асинхронный, и он умер из-за исключения в вашем коде.

Я использую этот класс в своем сервисе wcf для подключения - я делаю это через web.config, однако изменить его несложно, чтобы он выполнялся с атрибутом уровня класса для самой службы.

вы, вероятно, захотите убрать все контрактные вещи. Он используется в проекте, над которым я работаю, но никак не связан с этой проблемой.

 [AttributeUsage(AttributeTargets.Class)]
    public class FaultBehavior : Attribute, IServiceBehavior,  IEndpointBehavior
    {  

    public class SilverlightFaultMessageInspector : IDispatchMessageInspector
    {

        public void BeforeSendReply(ref Message reply, object correlationState)
        {
            Contract.Assume(reply !=null );
            if (reply.IsFault)
            {
                HttpResponseMessageProperty property = new HttpResponseMessageProperty();

                // Here the response code is changed to 200.
                property.StatusCode = System.Net.HttpStatusCode.OK;

                Contract.Assume(reply.Properties != null);
                reply.Properties[HttpResponseMessageProperty.Name] = property;
            }
        }

        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            // Do nothing to the incoming message.
            return null;
        }


    }


    #region IServiceBehavior Members

    void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {

    }

    void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        Contract.Assume( serviceHostBase != null);
        Contract.Assume(serviceHostBase.ChannelDispatchers != null);

        foreach (ChannelDispatcher cDispatcher in serviceHostBase.ChannelDispatchers)
        {
            Contract.Assume(cDispatcher != null);
            Contract.Assume(cDispatcher.Endpoints != null );
            foreach (EndpointDispatcher endpointDisbatcher in cDispatcher.Endpoints)
            {
                Contract.Assume(endpointDisbatcher != null);
                Contract.Assume(endpointDisbatcher.DispatchRuntime  != null);
                Contract.Assume(endpointDisbatcher.DispatchRuntime.MessageInspectors  != null);
                endpointDisbatcher.DispatchRuntime.MessageInspectors.Add(new SilverlightFaultMessageInspector());
            }
        }
    }

    void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {

    }

    #endregion

    #region IEndpointBehavior Members

    void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {

    }

    void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {

    }

    void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        Contract.Assume(endpointDispatcher != null);
        Contract.Assume(endpointDispatcher.DispatchRuntime != null);
        Contract.Assume(endpointDispatcher.DispatchRuntime.MessageInspectors != null);
        SilverlightFaultMessageInspector inspector = new SilverlightFaultMessageInspector();
        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
    }

    void IEndpointBehavior.Validate(ServiceEndpoint endpoint)
    {

    }

    #endregion
}

Затем вам нужно определить элемент, который появится в web.config lik this

public class FaultHandlerElement   : BehaviorExtensionElement 
{
    protected override object CreateBehavior()
    {
        return new FaultBehavior();
    }

    public override Type BehaviorType
    {
        get { return typeof(FaultBehavior); }
    }


}

и затем в веб-конфигурации вам нужно добавить это в раздел модели сервиса - исключение ошибки будет иметь волнистую линию под ним;)

<system.serviceModel>
    <extensions>
        <behaviorExtensions>
            <add name="faultBehaviourExtension"
  type="CopSilverlight.Web.FaultHandlerElement, CopSilverlight.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        </behaviorExtensions>
    </extensions

Затем вы подключаете свое поведение, чтобы использовать это так

   <serviceBehaviors>
                <behavior name="basicHttpBehaviour">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                    <faultBehaviourExtension />
                </behavior>

Альтернативное «исправление» - включить трассировку в ваших сервисах wcf. Следует отметить, что если вы не создадите каталог, он просто не создаст журнал

    <system.diagnostics>
        <sources>
            <source name="System.ServiceModel"
                switchValue="Information, ActivityTracing"
                propagateActivity="true">
                <listeners>
                    <add name="traceListener"
  type="System.Diagnostics.XmlWriterTraceListener"
  initializeData="c:\logs\appName\wcf.svclog"  />
                </listeners>
            </source>
        </sources>
    </system.diagnostics>

регистрация не идеальна, хотя первое решение на самом деле решает проблему.

Я реализовал оба из них, и теперь я получаю исключения, всплывающие в моем приложении Silverlight, как и следовало ожидать.

3 голосов
/ 01 ноября 2010

Интересно, совпадает ли это с этим

Кража из этого ответа:

Проверьте реестр в HKCU \ Software \ Microsoft \Windows \ CurrentVersion \ Internet Settings для значения с именем ReceiveTimeout и удалите, если оно есть.- cdm9002 4 мая в 14: 30

Или сбросьте его на значение по умолчанию, которое составляет 1 час (3600000 миллисекунд).

3 голосов
/ 30 сентября 2010

Может ли это быть что-то в сети.

В в этом они получили такое же сообщение об ошибке, но на самом деле это был тайм-аут 504 шлюза.

Если, например, выиметь прокси-сервер между приложением silverlight и сервером, который закрывает соединение, чтобы обратный вызов не мог связаться с клиентом.

1 голос
/ 18 сентября 2010

В конфигурационных файлах выше, похоже, что они из конфигурации сервера. Вы также проверили конфигурацию на стороне клиента? Свойства SendTimeout и ReceiveTimeout на клиентском канале по умолчанию равны одной минуте, но, возможно, их можно было изменить или переопределить. И, конечно, вы должны проверить как ваши XML-файлы конфигурации, так и место, где вы создаете привязку в коде, так как там можно установить свойства, которые конфликтуют с вашими файлами конфигурации. (Как на клиенте, так и на сервере.)

0 голосов
/ 04 октября 2010

Просто из любопытства, какой сейчас установлен idleTimeout в web.config?Возможно ли установить до 10 минут?

ОБНОВЛЕНИЕ

Так вот ваша проблема!Это известная проблема с idleTimeout!Просто удалите эту настройку, и все снова заработает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...