Как определить, что служба WCF готова? - PullRequest
11 голосов
/ 22 марта 2011

У меня есть следующий сценарий:

Мое основное приложение (APP1) запускает процесс (SERVER1).SERVER1 размещает службу WCF через именованный канал.Я хочу подключиться к этому сервису (из APP1), но иногда он еще не готов.

Я создаю ChannelFactory, открываю его и позволяю генерировать клиента.Если я теперь вызываю метод для сгенерированного Клиента, я получаю исключение, которое говорит мне, что Enpoint не был найден:

var factory = new ChannelFactory<T>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe//localhost/myservice");
factory.Open()

var Client = factory.CreateChannel();
Client.Foo();

Если я немного подожду перед вызовом службы, все в порядке;

var Client = factory.CreateChannel();
Thread.Sleep(2000);
Client.Foo();

Как я могу убедиться, что Служба готова, не ожидая случайного количества времени?

Ответы [ 5 ]

6 голосов
/ 22 марта 2011

Если в общем случае вы просто ждете запуска этой другой службы, то вы также можете использовать подход, предусматривающий использование метода «Ping» на вашем интерфейсе, который ничего не делает, и повторять попытки, пока это не начнет отвечать.

Мы делаем аналогичную вещь: мы пытаемся вызвать метод ping в цикле при запуске (1 секунда между повторными попытками), записывая в наши журналы (но в конечном итоге игнорируя) любые TargetInvocationException, которые происходят, пытаясь достичь нашегооказание услуг.Как только мы получим первый правильный ответ, мы продолжим работу.

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

5 голосов
/ 22 марта 2011

Сервис может сигнализировать о событии [см. Примечание], когда хост сервиса полностью открыт и событие Opened прослушивателя канала сработало.Приложение будет ожидать события перед использованием своего прокси.


Примечание. Использовать именованное событие легко, поскольку тип .NET EventWaitHandle дает вам все необходимое.Использование анонимного события предпочтительнее, но требует немного больше работы, поскольку типы оболочки событий .NET не дают наследуемого дескриптора события.Но все же возможно, если вы сами P / Invoke API Windows DuplicateHandle получите наследуемый дескриптор, а затем передаете значение дублированного дескриптора дочернему процессу в его аргументах командной строки.

2 голосов
/ 22 марта 2011
  1. Если вы используете .Net 4.0, вы можете использовать WS-Discovery , чтобы служба объявила о своем присутствии через Broadcast IP.

  2. Служба также может отправить сообщение в очередь (привязка MSMQ) с коротким сроком службы, скажем, несколько секунд, которое может отслеживать ваш клиент.

  3. Пусть служба создаст сигналфайл, затем используйте FileSystemWatcher на клиенте, чтобы определить, когда он был создан.

  4. Просто while (!alive) try { alive = client.IsAlive(); } catch { ...reconnect here... } (в вашем контракте на обслуживание у вас просто есть IsAlive() return true)

0 голосов
/ 05 марта 2017

У меня была такая же проблема, и при использовании net.pipe *: // localhost / serviceName * я решил ее, посмотрев на процесс самостоятельного размещения приложения.

То, как я это сделал, было с помощью служебного класса, вот код.

public static class ServiceLocator
{
    public static bool IsWcfStarted()
    {
        Process[] ProcessList = Process.GetProcesses();
        return ProcessList.Any(a => a.ProcessName.StartsWith("MyApplication.Service.Host", StringComparison.Ordinal));
    }


    public static void StartWcfHost()
    {

        string path = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

        var Process2 = new Process();
        var Start2 = new ProcessStartInfo();
        Start2.FileName = Path.Combine(path, "Service", "MyApplication.Service.Host.exe");            
        Process2.StartInfo = Start2;
        Process2.Start();
    }
}

сейчас мое приложение не называется MyApplication, но вы поняли мою точку зрения ... Теперь в моих клиентских приложениях, которые используют хост, у меня есть этот вызов:

if (!ServiceLocator.IsWcfStarted())
{
    WriteEventlog("First instance of WCF Client... starting WCF host.")
    ServiceLocator.StartWcfHost();
    int timeout=0;
    while (!ServiceLocator.IsWcfStarted()) 
    {
      timeout++;
      if(timeout> MAX_RETRY)
      {
       //show message that probably wcf host is not available, end the client
       ....
      }

    }
}

Это решило 2 вопроса, 1. Ошибки кода, которые у меня были устранены из-за состояния гонки, и 2 2. Я контролируемым образом знаю, произошел ли сбой в работе хоста из-за какой-либо проблемы или неправильной конфигурации.

Надеюсь, это поможет.

Walter

0 голосов
/ 02 августа 2012

Я прикрепил обработчик событий к client.InnerChannel.faulted, затем уменьшил reliableSession до 20 секунд. В обработчике событий я удалил существующий обработчик, затем запустил асинхронный метод, чтобы попытаться подключиться снова, и снова подключил обработчик событий. Кажется, работает.

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