WCF Ожидание завершения операций при закрытии ServiceHost - PullRequest
5 голосов
/ 16 мая 2011

Я создаю сервер WCF SOAP с операцией, выполнение которой занимает некоторое время:

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    string LongRunningOperation();
}

[ServiceBehavior(
    ConcurrencyMode = ConcurrencyMode.Multiple,
    UseSynchronizationContext = false,
    InstanceContextMode = InstanceContextMode.Single)]
class MyService : IMyService
{
    public string LongRunningOperation()
    {
        Thread.Sleep(20000);
        return "Hey!";
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyService instance = new MyService();
        ServiceHost serviceHost = new ServiceHost(instance);
        BasicHttpBinding binding = new BasicHttpBinding();
        serviceHost.AddServiceEndpoint(typeof(IMyService), binding, "http://localhost:9080/MyService");
        serviceHost.Open();
        Console.WriteLine("Service running");
        Thread.Sleep(10000);
        serviceHost.Close();
        Console.WriteLine("Service closed");
        Thread.Sleep(30000);
        Console.WriteLine("Exiting");
    }
}

ServiceHost открывается, и через 10 секунд я закрываю его.

При вызове serviceHost.Close () все подключенные клиенты, ожидающие завершения операции LongRunningOperation , немедленно отключаются.

Есть ли ожидание закрытия ServiceHost более чистым способом? То есть я хочу отключить прослушиватели службы, а также дождаться завершения всех подключенных в данный момент клиентов (или указать максимальное время ожидания).

Ответы [ 4 ]

4 голосов
/ 16 мая 2011

Я удивлен, позвонив ServiceHost.Close не позволяет завершить LongRunningOperation.

Вся архитектура настроена так, чтобы время могло корректно завершаться (например, разница между переходами Close и Abort.). Согласно документам MSDN:

Этот метод вызывает СвязьОбъект изящно переход из любого состояния, кроме Закрытое состояние, в Закрытое государство. Метод Close позволяет любой незавершенные работы должны быть завершены до возвращение.

Также для этой цели на ServiceHost есть CloseTimeout. Вы пытались установить значение CloseTimeout больше 20 секунд? (Согласно Reflector значение по умолчанию CloseTimeout для ServiceHost составляет 10 секунд ...)

2 голосов
/ 16 мая 2011

То, что вы делаете, мне кажется неправильным. ServiceHost никогда не должен внезапно закрываться. Это услуга и должна оставаться доступной. Нет реального способа закрыть изящно без участия клиента. Когда я говорю «изящно», это также субъективно с точки зрения клиентов.

Так что я не думаю, что понимаю ваши требования вообще, однако одним из способов было бы реализовать шаблон публикации / подписки, и, когда хост будет готов закрыть, уведомить всех подписчиков об этом событии, чтобы все соединения могли быть закрыты каждым соответствующий клиент. Подробнее об этом можно прочитать здесь http://msdn.microsoft.com/en-us/magazine/cc163537.aspx

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

2 голосов
/ 16 мая 2011

В принципе, я думаю, что что-то вроде следующего должно быть возможным, хотя я не реализовал это, чтобы подтвердить все детали:

  • Реализовать собственный IOperationInvoker, оборачивающий обычный OperationInvoker Диспетчера (вы 'вы захотите, чтобы IServiceBehavior установил упакованный инвокер при построении среды выполнения диспетчера служб)
  • пользовательский активатор в основном делегировал бы реальный, но также обеспечивал бы функцию «привратника» для отклонения новогозапросы (например, вызовите какое-то исключение), когда хост службы собирается завершить работу.
  • он также отслеживал бы все еще выполняющиеся вызовы операций и устанавливал событие по окончании или по истечении времени ожидания последнего вызова операции.
  • главный хост-поток затем ожидал бы, что завершивший вызов завершил"событие перед звонком serviceHost.Close().
1 голос
/ 16 мая 2011

Вы описываете функциональность на стороне клиента.Похоже, вам следует обернуть объект servicehost, а затем прокси-сервер отклоняет новые запросы, когда он «закрывается».Вы не закроете реальный сервисный хост, пока все вызовы не будут обслужены.

Вы также должны взглянуть на асинхронную CTP.Поместить этот вид логики в объект «Задача» на стороне потребителя будет намного проще с помощью следующего класса TaskCompletionSource.

Проверьте это видео из dnrtv out.Речь идет не о wcf, а о грядущей поддержке языка и классов для асинхронности.

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