ServiceHost.Close не возвращается в течение… - PullRequest
1 голос
/ 06 ноября 2010

Вызов ServiceHost.Close() позволяет элегантно завершить работу экземпляра хоста, позволяя завершать текущие вызовы и одновременно отказывать в будущих клиентских вызовах. Предполагая, что ServiceHost.CloseTimeout установлен на 10 секунд, тогда экземпляр ServiceHost будет блокироваться на 10 секунд, ожидая, пока Close() вернет

а) Что произойдет, если Close() не вернется в течение 10 секунд? Будет ли ServiceHost экземпляр принудительно отключаться без каких-либо исключений?

b) Каковы общие сценарии, когда Close() не возвращается в течение указанного времени? Возможно, когда клиентский звонок еще обрабатывается?

спасибо

РЕПЛИКА:

Я в замешательстве. В вашем примере хост службы действительно ожидает завершения операции, но в моем примере это не так, поскольку Console.WriteLine("GetDog completed"); (вызывается в GetDog()) не выполняется:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Threading;

namespace ConsoleApplication1
{
    [ServiceContract]
    public interface IDogs
    {
        [OperationContract]
        string GetDog();
    }

    public class Animals : IDogs
    {
        public string GetDog()
        {
            Thread.Sleep(30000);
            Console.WriteLine("GetDog completed"); // this doesn't get executed
            return "dalmatian";
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            ServiceHost host1 = 
                new ServiceHost(typeof(Animals),new Uri("http://localhost:8000"));
            host1.AddServiceEndpoint(typeof(IDogs), new BasicHttpBinding(), "Dogs");

            ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
            behavior.HttpGetEnabled = true;
            host1.Description.Behaviors.Add(behavior);

            host1.AddServiceEndpoint(
                typeof(IMetadataExchange),
                MetadataExchangeBindings.CreateMexHttpBinding(),
                "mex");

            host1.Open();
            Thread.Sleep(6000);
            host1.Close();
        }
    }

Кстати, почему не генерируется исключение в основном потоке (который вызывает host.Close())? Вместо этого он выбрасывается из потока, который выполняет Service.doFoo()?!

1 Ответ

1 голос
/ 07 ноября 2010

а) Будет выдано исключение TimeoutException.

b) Может истечь время ожидания, если вы переопределили OnClosing, OnClose(TimeSpan) или OnClosed чем-то трудоемким. И, да, согласно этому списку ошибок , он будет ожидать отправки операции. Смотри SfxCloseTimedOutWaitingForDispatchToComplete. Нужно проверить это все же.

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

class Program
{
    static void Main(string[] args)
    {
        //Server
        string baseUri = "http://localhost:8080/test/";
        ServiceHost host = new ServiceHost(new Service(), new Uri(baseUri));
        BasicHttpBinding binding = new BasicHttpBinding();
        var endpoint = host.AddServiceEndpoint(typeof(IService), binding, baseUri);
        host.Closed += ((sender, arguments) => Console.WriteLine("Closed"));
        host.Open();

        //Client
        ChannelFactory<IService> factory = new ChannelFactory<IService>(endpoint);
        new Action(() => 
        {
            try
            {
                factory.CreateChannel().DoFoo();
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }).BeginInvoke(null, null);

        //Making sure request has reached the server
        Thread.Sleep(1000);

        host.Close();
    }
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service : IService
{
    public void DoFoo()
    {
        Console.WriteLine("DoFoo started");
        Thread.Sleep(10000);
        Console.WriteLine("DoFoo finished");
    }
}

[ServiceContract]
interface IService
{
    [OperationContract]
    void DoFoo();
}

Выход:

        DoFoo started
    An error occurred while receiving the HTTP response to http://localhost:8080/tes
    t/. This could be due to the service endpoint binding not using the HTTP protoco
    l. This could also be due to an HTTP request context being aborted by the server
     (possibly due to the service shutting down). See server logs for more details.
    DoFoo finished
    Closed
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...