Проблемы с одноэлементным шаблоном внутри метода сервиса WCF - PullRequest
8 голосов
/ 01 августа 2011

Я пойду вперед и скажу: я немного новичок в WCF.

Я работаю над серверной подпрограммой, которая отвечает за выполнение большой бизнес-логики. Он доступен с клиента через WCF.

Мой основной метод WCF вызывает несколько других частных методов. Вместо того чтобы передавать все «справочные данные», необходимые для бизнес-логики каждому частному методу, я решил использовать одноэлементный экземпляр класса с именем DataProvider, который содержит все эти «справочные данные».

В конце процедуры я «освобождаю» данные поиска DataProvider, поэтому при следующем выполнении подпрограммы будут использоваться самые последние данные поиска.

Итак, вот упрощенный пример:

 public void Generate()
 {
      try
      {
           //populate singleton DataProvider with it's lookup data...
           DataProvider.Instance.LoadLookupData();

           //do business logic...
      }
      finally
      {
           //release provider's lookup data...
           DataProvider.Release();
      }
 }

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

Итак ...

Какие у меня есть варианты?

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

Я считаю, что служба WCF настроена как "Per-Call". Я не уверен, есть ли способ настроить службу WCF, чтобы статическая память не распределялась между вызовами службы.

Любая помощь будет оценена.

Ответы [ 3 ]

8 голосов
/ 01 августа 2011

По умолчанию WCF использует «Per-Call», что означает, что для каждого вызова клиента создается новый экземпляр службы WCF.Теперь, когда вы реализовали синглтон, хотя новый экземпляр WCF создан, он по-прежнему вызывает ваш синглтон.

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

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

InstanceContextMode = InstanceContextMode.Single
ConcurrencyMode = ConcurrencyMode.Multiple  

. Это означает, что автоматически создаст синглтон для вас с помощью WCF, поэтому вам не придется делать это самостоятельно, во-вторых, это будетsupport> 1 одновременный пользователь (ConcurrencyMode.Multiple).

Теперь, если у вас меняется поиск и его необходимо перезагрузить через некоторое время, я все равно рекомендую использовать

InstanceContextMode = InstanceContextMode.Single 
ConcurrencyMode = ConcurrencyMode.Multiple

но внутри вашего кеша кода он и затем истекает кеш в определенное время или в относительное время (1 час).

Вот несколько ссылок, которые могут вам помочь: 3 способа управления экземплярами WCF(За звонок, за сеанс и в одиночку)

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

4 голосов
/ 01 августа 2011

Статические переменные в службе WCF всегда совместно используются экземплярами независимо от настройки WCF InstanceContextMode. Кажется, вам лучше использовать шаблон кэширования для поиска данных. ответы на этот вопрос о кешировании предоставляют некоторые альтернативы прокручиванию ваших собственных, хотя они немного устарели.

Кроме того, если вы решите сделать весь экземпляр службы одиночным (InstanceContextMode = Single)это самое простое решение, имейте в виду, что вы, как правило, убьете масштабируемость службы, если не сделаете свой код многопоточным (ConcurrencyMode = Multiple) .Если вы можете отключить потокобезопасный код во сне, то вам может пригодиться одноэлементная служба.

1 голос
/ 01 августа 2011

самое простое - использовать механизм синхронизации - вы смотрели на блокировку (...) - это будет действовать как привратник, как критическая секция (если вы сталкивались с таковыми в программировании Windows)

определить статический объект в вашем классе

т.е.

static object lockObject = new object();

и используйте его в методе Generate

1010 * т.е. *

void Generate()
{
    lock(lockObject)
    {
    ...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...