WCF PollingDuplexHttpBinding с тайм-аутами и ошибками клиента Silverlight - PullRequest
3 голосов
/ 18 октября 2010

Я создаю настольное приложение WPF 3.5 с собственной службой WCF.

Служба имеет конечную точку PollingDuplexHttpBinding, определенную следующим образом:

public static void StartService()
    {
        var selfHost = new ServiceHost(Singleton, new Uri("http://localhost:1155/"));

        selfHost.AddServiceEndpoint(
            typeof(IMyService), 
            new PollingDuplexHttpBinding(PollingDuplexMode.MultipleMessagesPerPoll) {ReceiveTimeout = new TimeSpan(1,0,0,0)},
            "MyService"
        );

        ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
        smb.HttpGetEnabled = true;
        selfHost.Description.Behaviors.Add(smb);

        selfHost.AddServiceEndpoint(typeof(IPolicyRetriever), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());

        selfHost.Open();
    }

Примечание: IPolicyRetriever - это служба, которая позволяет мне определять файл политики

Это работает, и я вижу свой сервис в моем клиентском приложении Silverlight. Затем я создаю ссылку на прокси в коде Silverlight так:

        EndpointAddress address = new EndpointAddress("http://localhost:1155/MyService");

        PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding(PollingDuplexMode.MultipleMessagesPerPoll);
        binding.ReceiveTimeout = new TimeSpan(1, 0, 0, 0);
        _proxy = new MyServiceClient(binding, address);
        _proxy.ReceiveReceived += MessageFromServer;
        _proxy.OrderAsync("Test", 4);

И это тоже отлично работает, связь работает!

Но если я оставлю это в покое (то есть не отправляю сообщения с сервера) на более чем 1 минуту, а затем попытаюсь отправить сообщение клиенту из приложения сервера WPF, я получаю ошибки тайм-аута, например:

Превышен тайм-аут канала IOutputChannel при попытке отправки после 00:01:00. Увеличьте значение тайм-аута, передаваемое вызову Send, или увеличьте значение SendTimeout в Binding. Время, отведенное для этой операции, могло быть частью более длительного времени ожидания.

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

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

Объект связи System.ServiceModel.Channels.ServiceChannel нельзя использовать для связи, поскольку он был прерван

Как я могу попытаться выяснить, что здесь не так?

1 Ответ

2 голосов
/ 19 октября 2010

WPF использует wsDualHttpBinding, Silverlight - дуплекс опроса.WPF решение простое;Silverlight требует ServiceHostFactory и немного больше кода.Кроме того, Silverlight Server никогда не отправляет сообщения, а клиент опрашивает сервер и получает его сообщения.

После многих проблем с PollingDuplexHttpBinding я решил использовать CustomBinding без MultipleMessagesPerPoll.

web.config

<system.serviceModel>
    <behaviors>
        <serviceBehaviors>
            <behavior name="SlApp.Web.DuplexServiceBehavior">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>

  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

    <services>
        <service behaviorConfiguration="SlApp.Web.DuplexServiceBehavior" name="SlApp.Web.DuplexService">
            <endpoint address="WS" binding="wsDualHttpBinding" contract="SlApp.Web.DuplexService" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        </service>
    </services>      
</system.serviceModel>

DuplexService.svc:

<%@ ServiceHost Language="C#" Debug="true" Service="SlApp.Web.DuplexService" Factory="SlApp.Web.DuplexServiceHostFactory" %>

DuplexServiceHostFactory.cs:

    public class DuplexServiceHostFactory : ServiceHostFactoryBase
    {
        public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
        {
            return new DuplexServiceHost(baseAddresses);
        }
    }

    class DuplexServiceHost : ServiceHost
    {
        public DuplexServiceHost(params Uri[] addresses)
        {
            base.InitializeDescription(typeof(DuplexService), new UriSchemeKeyedCollection(addresses));
        }

        protected override void InitializeRuntime()
        {
            PollingDuplexBindingElement pdbe = new PollingDuplexBindingElement()
            {
                ServerPollTimeout = TimeSpan.FromSeconds(3),
                //Duration to wait before the channel is closed due to inactivity
                InactivityTimeout = TimeSpan.FromHours(24)
            };

            this.AddServiceEndpoint(typeof(DuplexService),
                new CustomBinding(
                    pdbe,
                    new BinaryMessageEncodingBindingElement(),
                    new HttpTransportBindingElement()), string.Empty);

            base.InitializeRuntime();
        }
    }

Код клиента Silverlight:

address = new EndpointAddress("http://localhost:43000/DuplexService.svc");
binding = new CustomBinding(
            new PollingDuplexBindingElement(),
            new BinaryMessageEncodingBindingElement(),
            new HttpTransportBindingElement()
        );
proxy = new DuplexServiceClient(binding, address);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...