0

我正在引用一个(黑匣子)dll,它的初始化非常昂贵(需要 3-4 秒)。它由具有数百个同时用户的 asp.net 应用程序使用。

由于昂贵的初始化,我不能将它用作实例变量。我的第一个想法是将实例存储在静态变量中,并使用 c# lock() 方法来避免竞争条件。这很好用,但是当多个用户想要同时访问该库时,围绕单个静态变量的 lock() 方法显然效率低下。

我想实现一个对象池,以便可以使用该库的多个实例。我不能使用 COM+。当池将由 asp.net 应用程序使用时,在 c#、.Net 4.5.1 中实现对象池的最佳方法是什么?

这篇 MSDN 文章有很多引用建议使用 ConcurrentBag,但很多人说这在单个线程从池中添加/删除项目时效果最好。在我的情况下,多个线程将添加/删除项目,所以这种方法似乎不适合 asp.net,但如果我说错了,请纠正我:https ://msdn.microsoft.com/ zh-CN/图书馆/ff458671(v=vs.110).aspx

我发现这个答案非常有用,但它已经过时了: C# Object Pooling Pattern implementation

4

1 回答 1

1

ConcurrentBag是对象池的最佳结构。

您误解了“当单个线程从池中添加/删除项目时这种方法效果最好”的建议。一个更好的说法是“当从池中删除的线程很有可能成为将对象放入池中的同一线程时,AConcurrentBag效果最佳” ,这正是您的对象池将要做的。

工作方式ConcurrentBag是每个线程都有一个线程本地对象集合。当您添加到ConcurrentBag它时,它会插入到该线程本地集合中,当您从中删除时,ConcurrentBag它首先尝试从线程本地集合中删除,但如果它为空,它将转到另一个线程并将其从另一个线程的集合中删除。

因此,建议将同一线程添加为删除的原因是,您不会将两个列表与锁绑定在一起,而不是单个列表。

您甚至可以使用单个线程来填充池,然后当工人取出项目时,他们将从初始化线程的池中窃取,然后从那时起将其返回到自己的池中从他们自己的池中提取。

于 2015-11-04T21:01:37.757 回答