Веб-служба WCF - использование блокировки вызовет проблемы?

У нас есть операция веб-службы WCF, которая используется для создания файлов PDF. Для этого мы используем сторонний инструмент (в частности, Syncfusion), который, возможно, не сможем заменить в данный момент.

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

Мы можем избавиться от проблемы, используя lock и убедившись, что только один поток выполняет критическую секцию:

Public Class GeneratorController
{
    // object we use for lock
    private static Object thisLock = new Object();

    public void Generate(ref PdfDocument pdfDocument)
    {
        lock (thisLock)
        {
             // critical section
        }
    }
}

Мои вопросы: это хорошая идея? Не вызовет ли это каких-либо проблем, если у нас будет такой код в веб-сервисе?

Примечание

Это не вопрос о Syncfusion. Это вопрос об использовании lock в веб-сервисе. Не меняйте теги на syncfusion, пожалуйста.


person Szymon    schedule 09.10.2013    source источник
comment
Я не знаком с Syncfusion. Можно ли создать несколько одновременных экземпляров объекта? Я бы подумал, что если у вас есть отдельные экземпляры, вам не нужно блокировать.   -  person Tim    schedule 09.10.2013
comment
Я тоже так думаю, но проблема в нем. Может быть, они используют что-то статичное в своем коде...   -  person Szymon    schedule 09.10.2013


Ответы (3)


WCF поддерживает синхронизированный вызов ваших сервисных объектов, в зависимости от ваших потребностей вы можете изучить следующие два свойства:

Если вы не можете запустить несколько экземпляров стороннего компонента, и компонент не разрешает одновременный доступ (наихудший случай), вы можете указать InstanceContextMode = Single и ConcurrencyMode = Single; В этом случае WCF создаст только одну копию вашего объекта WCF (который, как я предполагаю, является оболочкой для стороннего компонента), и за раз обрабатывается только один запрос. Запросы будут поставлены в очередь и обработаны в порядке FIFO. Вам не нужно использовать блокировку внутри вашей службы wcf, поскольку среда выполнения WCF гарантирует, что у вас есть синхронизированный доступ к вашим объектам wcf.

person X.J    schedule 14.10.2013

Проблема, которую я вижу здесь, — нехватка ресурсов.

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

  • Поток A требует блокировки
  • Поток B ожидает блокировки
  • Поток C ожидает блокировки
  • Поток A снимает блокировку. Блокировка произвольно назначается потоку C
  • Поток D ожидает блокировки. Теперь у вас есть потоки B и D, ожидающие выполнения.
  • Поток C снимает блокировку. Даже если поток B ожидает дольше всех, блокировка произвольно назначается потоку D.

И так продолжается до тех пор, пока время вызова WCF не истечет, и вы получите невозможную для воспроизведения ошибку.

Если бы мне пришлось реализовать это, у меня был бы один рабочий поток, предназначенный для создания файлов PDF. Этот поток запускается при первом запуске службы и ожидает получения задания из очереди заданий. Каждый запрос WCF будет помещать запрос в эту очередь, и он может каким-то образом заблокироваться, пока не узнает, что задание было обработано.

.NET 4.0 предоставляет для этого класс BlockingCollection. (См. этот вопрос)

Это дает вам подход без полного решения, потому что это не тривиальная проблема. Удачи!

person Andrew Shepherd    schedule 09.10.2013
comment
Спасибо за ответ, именно такую ​​информацию я и искал. Процесс в нашем случае довольно редкий, но такое голодание все же возможно. Я приму это к сведению. - person Szymon; 09.10.2013

Essential PDF — это потокобезопасный компонент, поэтому PDF-документ можно создавать в многопоточном состоянии. Не могли бы вы создать инцидент Direct-trac, чтобы получить решение.

person George    schedule 11.10.2013
comment
Ну, мы все еще изо всех сил пытаемся получить правильно работающую версию от Syncfusion, так что это не совсем так. - person Szymon; 04.01.2014