2013-03-04 6 views
3

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

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

Как вы можете видеть, я в настоящее время обертываю функции методов в операторе lock, чтобы предотвратить различные потоки из HttpModule, перезаписывающие свойства процессоров, хотя я знаю, что это может стать узким местом. Я задаюсь вопросом: есть ли шаблон дизайна или метод, с помощью которого я могу сделать свои процессоры потокобезопасными без блокировки?

public static ImageFactory AutoProcess(this ImageFactory factory) 
{ 
    if (factory.ShouldProcess) 
    { 
     // TODO: This is going to be a bottleneck for speed. Find a faster way. 
     lock (SyncLock) 
     { 
      // Get a list of all graphics processors that 
      // have parsed and matched the querystring. 
      List<IGraphicsProcessor> list = 
       ImageProcessorConfig.Instance.GraphicsProcessors 
       .Where(x => x.MatchRegexIndex(factory.QueryString) != int.MaxValue) 
       .OrderBy(y => y.SortOrder) 
       .ToList(); 

      // Loop through and process the image. 
      foreach (IGraphicsProcessor graphicsProcessor in list) 
      { 
       factory.Image = graphicsProcessor.ProcessImage(factory); 
      } 
     } 
    } 

    return factory; 

} 
+5

У вас есть доказательства того, что это * является узким местом? Не тратьте свое драгоценное время на опасные и сложные решения проблем, которые у вас нет. Если это узкое место, тогда первая попытка решения должна заключаться в том, чтобы * перемещать как можно больше работы за пределы замка *, а не пытаться устранить блокировку *. Незаконные замки * необычайно быстры *; мы говорим о наносекундах. Контрастные замки дороги; вы можете устранить конфликт, не делая так много работы внутри замка. –

+0

Честно говоря, я этого не делаю. Я бы подумал, что это будет так. Я зашел так далеко, как оптимизировал свой класс ImageFactory, чтобы он не нуждался в каких-либо блокировках вокруг «Bitmap's», и казалось, расточительно не оптимизировать процесс, учитывая, что я могу потенциально обрабатывать тысячи изображений. Я действительно не знал, что они так быстро. –

ответ

2

Интересует вас потребительская очередь производителя. В общем случае ваш HttpModule получит события (продюсер) и поставит их в очередь на один или несколько экземпляров IGraphicsProcessor (потребитель (ы)).

Это каноническое, простейший из возможных реализаций очереди производитель/потребитель: http://www.albahari.com/threading/part4.aspx#_Wait_Pulse_Producer_Consumer_Queue

Если вы намерены устранения блокировки, вы должны experiement с производителем/потребительских очередей с помощью бесплатного осуществления стопорное очереди, таких как System.Collections.Concurrent.ConcurrentQueue<T> в. NET 4.0.

+0

Я сейчас посмотрю на это. У меня на самом деле была открытая страница на другой вкладке. –

2

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

Если нет ясной причины, я бы разрешил несколько экземпляров каждого процессора изображений. Убедитесь, что процессор освобождает ссылки на данные, на которых он действует как можно раньше, чтобы позволить GC функционировать оптимально. Это имеет достоинства простоты и хорошее использование процессорных ядер.

Если есть ясная причина допускать только один экземпляр каждого процессора, вы можете улучшить свой код, избегая текущей ситуации, которую вы блокируете до тех пор, пока не завершит свою работу все процессоры. Вместо этого у вас может быть механизм для запроса каждого процессора, который вам нужен, для следующего элемента после завершения текущего элемента. Предложение Энтони использовать образец производителя/потребителя кажется для него прочным решением. Имейте в виду, что при таком подходе вы все равно будете сталкиваться с пропускной способностью каждого отдельного фильтра, и вы не сможете оптимально использовать все ядра ЦП.

+0

Одной из основных причин, по которым только один экземпляр был расшифрован.Я загружаю и создаю при запуске приложения все экземпляры интерфейса IGraphicsProcessor. Идея состоит в том, что библиотека может быть расширена посредством drop в dll's. –

+0

Если для экземпляров экземпляров очень дорого, вы можете использовать пул объектов для управления N экземплярами предварительно инициализированных объектов. Если это не дорого для экземпляра экземпляра, нет причин для их предварительного создания. Есть ли у вас конкретные измерения (или ожидания для будущих плагинов), что издержки на инициализацию будут высокими? –

+0

Ну нет. Любая будущая реализация должна быть легкой. В настоящее время, хотя, я должен был бы создать и экземпляр всех из них, каждый раз, когда я вызываю метод, чтобы использовать регулярное выражение из каждого из них для синтаксического анализа запроса. –

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