3

我的成像库中有以下代码,它利用处理器列表动态操作由HttpModule.

目前,每个处理器只创建一个实例以降低内存开销,并且每个处理器都具有可写属性,有助于确定处理每个匹配的查询字符串参数并存储要处理的解析值的顺序。

如您所见,我目前正在将方法功能包装在一个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;

}
4

2 回答 2

2

您可能对生产者消费者队列感兴趣。通常,您会接收事件(生产者)并将它们排队到(消费者)的HttpModule一个或多个实例。IGraphicsProcessor

这是规范的、最简单的生产者/消费者队列实现:http ://www.albahari.com/threading/part4.aspx#_Wait_Pulse_Producer_Consumer_Queue

如果您打算消除锁定,您应该使用无锁队列实现来体验生产者/消费者队列,例如System.Collections.Concurrent.ConcurrentQueue<T>在 .NET 4.0 中。

于 2013-03-04T23:46:07.090 回答
2

要么你需要通过没有多个处理器来降低内存压力(然后你需要至少允许一个给定的处理器来完成它当前的工作),或者你需要完全并发。

除非有明确的理由不这样做,否则我将允许每个图像处理器有多个实例。确保处理器尽可能早地释放对其正在操作的数据的引用,以使 GC 以最佳方式运行。这具有简单的优点,以及对 CPU 内核的良好利用。

如果有明确的理由只允许每个处理器的一个实例,您可以通过避免当前的情况来改进您的代码,即在所有处理器完成工作之前锁定。相反,一旦当前项目完成,您可以有一种机制来请求您需要处理下一个项目的每个处理器。@anthony 建议使用生产者/消费者模式似乎是一个可靠的解决方案。请记住,使用这种方法,您仍然会成为每个过滤器吞吐量的瓶颈,并且您可能无法最佳地利用所有 CPU 内核。

于 2013-03-04T23:47:13.450 回答