WCF Proxy Client требует времени для создания любого кеша или одноэлементного решения для него - PullRequest
7 голосов
/ 17 июня 2011

у нас есть более чем дюжина сервисов wcf и вызывается с использованием привязки TCP.В разных местах кода много вызовов одного и того же сервиса wcf.

AdminServiceClient client = FactoryS.AdminServiceClient (); // это занимает значительное время.и

client.GetSomeThing (param1);client.Close ();

Я хочу кэшировать клиента или произвести его из синглтона.так что я могу сэкономить время, это возможно?

Thx

Ответы [ 2 ]

8 голосов
/ 17 июня 2011

Да, это возможно.Вы можете сделать прокси-объект видимым для всего приложения или обернуть его в одноэлементный класс для аккуратности (мой предпочтительный вариант).Однако, если вы собираетесь повторно использовать прокси для службы, вам придется обрабатывать сбои каналов.

Сначала создайте свою переменную singleton class / cache / global, которая содержит экземпляр прокси (или прокси), которыйВы хотите использовать повторно.

Когда вы создаете прокси, вам нужно подписаться на событие Faults на внутреннем канале

proxyInstance.InnerChannel.Faulted += new EventHandler(ProxyFaulted);

, а затем поместить некоторый код переподключения в обработчик событий ProxyFapted.Событие Faults сработает, если служба прервется или время соединения истечет из-за простоя.Событие с ошибкой сработает только в том случае, если у вас включена надежная сессия для вашей привязки в файле конфигурации (если она не указана, по умолчанию она включена для netTcpBinding).

Редактировать: если вы не хотите, чтобы ваш прокси-канал был открытвсе время вам придется проверять состояние канала перед каждым его использованием и заново создавать прокси-сервер, если он неисправен.Как только канал вышел из строя, нет другого выбора, кроме как создать новый.

Edit2: единственная реальная разница в нагрузке между сохранением канала открытым и его закрытием каждый раз, когда пакет keep-alive отправляется наобслуживание и подтверждается время от времени (что стоит за событием сбоя вашего канала).С 100 пользователями я не думаю, что это будет проблемой.

Другой вариант - поместить ваше создание прокси в блок использования, где он будет закрыт / расположен в конце блока (что считается плохой практикой ).Закрытие канала после вызова может привести к зависанию приложения, поскольку служба еще не завершила обработку.Фактически, даже если ваш вызов службы был асинхронным или контракт на обслуживание метода был односторонним, код закрытия канала будет блокироваться до тех пор, пока служба не будет завершена.

Вот простой одноэлементный класс, который долженимейте то, что вам нужно:

public static class SingletonProxy
{
    private CupidClientServiceClient proxyInstance = null;
    public CupidClientServiceClient ProxyInstance
    {
        get
        {
            if (proxyInstance == null)
            {
                AttemptToConnect();
            }
            return this.proxyInstance;
        }
    }

    private void ProxyChannelFaulted(object sender, EventArgs e)
    {
        bool connected = false;
        while (!connected)
        {
            // you may want to put timer code around this, or 
            // other code to limit the number of retrys if 
            // the connection keeps failing
            AttemptToConnect();
        }
    }

    public bool AttemptToConnect()
    {
        // this whole process needs to be thread safe
        lock (proxyInstance)
        {
            try
            {
                if (proxyInstance != null)
                {
                    // deregister the event handler from the old instance
                    proxyInstance.InnerChannel.Faulted -= new EventHandler(ProxyChannelFaulted);
                }

                //(re)create the instance
                proxyInstance = new CupidClientServiceClient();
                // always open the connection
                proxyInstance.Open();

                // add the event handler for the new instance
                // the client faulted is needed to be inserted here (after the open)
                // because we don't want the service instance to keep faulting (throwing faulted event)
                // as soon as the open function call.
                proxyInstance.InnerChannel.Faulted += new EventHandler(ProxyChannelFaulted);

                return true;
            }
            catch (EndpointNotFoundException)
            {
                // do something here (log, show user message etc.)
                return false;
            }
            catch (TimeoutException)
            {
                // do something here (log, show user message etc.)
                return false;
            }
        }
    }
}

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

2 голосов
/ 20 июня 2011

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

Я бы посоветовал вам использовать многократно используемую реализацию ChannelFactory , если вы этого еще не сделали и посмотрите, есть ли у вас проблемы с производительностью.

...