2014-01-10 6 views
0

У меня есть приложение ASP.NET, которое использует «служебную ссылку» на сторонний платежный процессор. пример кода, который я скачал из платежной системы включает в себя следующее:Безопасный доступ к каналу WCF

public class SoapAPIUtilities{ 

     private static CustomerProfileWS.Service service = null; 

     public static CustomerProfileWS.Service Service{ 
     get{ 
      if(service == null){ 
       service = new CustomerProfileWS.Service(); 
      } 
      return service; 
     } 
     } 
    } 

я произвожу CustomerProfileWS.Serviceautomatically using Visual Web Developer: его автоматически генерируемый реализация является подкласс подкласса ServiceModel.ClientBase, который MSDN документы, как «членов экземпляров не гарантируют безопасность потока ».

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

Если это не поточно-то, что это лучший способ, чтобы сделать его поточно-:

  • Wrap класс сбруя, который реализует блокировку вокруг статического одноточечного (e.g. as shown here)?
  • Не используйте статический синглтон; вместо этого создайте несколько/временных CustomerProfileWS.Service экземпляров по мере необходимости, как локальные переменные в методах страниц ASP.NET, которые в них нуждаются?

ответ

0

Я бы с 2-й вариант вы предлагаете ...

Не используйте статический синглтон; вместо этого создайте несколько/временных экземпляров CustomerProfileWS.Service по мере необходимости, как локальные переменные в методах страниц ASP.NET, в которых они нуждаются?

+0

Пожалуйста скажите мне ваши рассуждения? Мое беспокойство об этом методе заключается в том, что: а) я не знаю, нужно ли это b) Я не могу проверить, правильно ли обрабатывает удаленный/серверный конец параллельных запросов от одного и того же клиента/продавца/сайта. C) Потому что это не так. он в своей «образцовой программе» может не поддерживаться. – ChrisW

+0

Повторно создавая объект CustomerProfileWS.Service для каждого обрабатываемого платежа, вы полностью исключаете многопоточный сценарий. В этом отношении я бы очень отказался от запуска нескольких потоков в приложении ASP.NET для начала. – Jason

+0

Я не разворачиваю нити. Но если есть более одного одновременного пользователя веб-сайта, то не существует ли одновременно более одного экземпляра страницы ASPX (каждый со своим потоком)? – ChrisW

0

Я бы поменял его на private static readonly CustomerProfileWS.Service service = new CustomerProfileWS.Service();.

Это создаст ваш синглтон в потоковом безопасном режиме.

Однако, если несколько потоков обращаются к прокси-серверу WCF, можно закрыть соединение, а другое - в середине операции.

Я думаю, что прокси-сервер для каждого запроса ASP.NET может быть лучше подходит здесь.

+0

Моему коду не нужно явно открывать или закрывать канал, не так ли? Предполагая, что мой код никогда явно не открывает или не закрывает канал, является ли поток безопасным? Не подразумевает ли он сериализацию запросов, если он получает несколько одновременных запросов? – ChrisW

+0

Возможно, посмотрите http://stackoverflow.com/questions/3246634/do-i-need-to-close-a-net-service-reference-client-when-im-done-using-it – MattC

+0

Или http://garrettvlieger.com/blog/2009/09/closing-wcf-service-references/ – MattC

1

Создание прокси-нити, защищенной и одиночной, не подходит для веб-приложений.

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

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

Performance Improvement for WCF Client Proxy Creation

Другой способ заключается в создании пула прокси, так что вам не нужно создавать новый прокси каждый раз, но повторно использовать существующее, если оно доступно. В качестве примера можно найти здесь:

A Sample for WCF Client Proxy Pooling

+0

+1 Благодарим вас за ссылки. [Мой пример обертки вокруг синглтона] (http://codereview.stackexchange.com/q/38953/34757) пытается восстановить из-за ошибки, воссоздав синглтон, если он сработал. – ChrisW

+0

Это не сработает в этой ситуации: Thread1 делает 1 вызов. Thread2 делает другой вызов. Неисправность Thread1 завершается ошибкой, и канал становится неисправным.Thread2 не может продолжить операцию, потому что канал уже поврежден Thread1. Даже если вы восстановите прокси-сервер, два ваших веб-запроса (или столько, сколько у вас есть в одно и то же время) не удастся, потому что у одного из них возникла проблема. – Cosmin

+0

Я думаю, что это сработает? Темы «сделать вызов» путем создания экземпляра класса Authorize в операторе using, например. 'using (Авторизовать auth = new Authorize()) {auth-> IsAlive(); } 'Существует блокировка (' Monitor.Enter'), которая гарантирует, что вызов Thread2 в конструкторе 'Authorize' не будет завершен до тех пор, пока Thread1 не удалит свой экземпляр Authorize, оставив синглтон в хорошем состоянии или в состоянии отказа , Если это не сработало, конструктор Authorize Thread2 воссоздает синглтон, после того, как он приобретет блокировку, прежде чем он вернется к вызывающему абоненту и позвонит вызывающему абоненту использовать другие сообщения авторизации. – ChrisW

Смежные вопросы