【发布时间】:2015-08-15 22:19:09
【问题描述】:
我在 .Net 4.5 中有一个 ConcurrentBag,我从数据库中存储了大约 4,000 行。我正在存储 DTO。
我的整个应用程序都依赖于此。我有返回整个列表的函数,也有返回单个项目的函数。我的代码中有很多地方我正在对集合等进行 LINQ 查询。
我将其全部投入生产,在获得大量流量的站点上,并立即 100% cpu。我用了iis诊断工具,果然有50+线程死锁,在ConcurrentBag上等待。
文档说这个集合是线程安全的,但要么这不是真的,要么这个集合的性能不好,因此间接导致它不是线程安全的。
不幸的是,这个集合不是只读的。如果通过 ID 查找的函数之一返回 null,它将访问 Web 服务,并添加它。
我也将它转换为 ConcurrentDictionary,并且遇到了同样的问题。在 .Values 属性上锁定天数。
在最极端的情况下,最快和最线程安全的解决方案是什么?
private ConcurrentBag<Students> _students;
public static ConcurrentBag<DestinyHash> GetStudents()
{
if (_students == null) { _students = new ConcurrentBag<Students>(); }
return _students;
}
public static Student GetStudentByID(int id)
{
if (GetStudents().Any(x => x.id == id)) { return ... }
_students.Add(getStudentFromDb(id));
return...
}
使用示例 - 遍布整个应用程序。
Helper.GetStudents().FirstOrDefault(x => x.name == "foo" && x.status == "bar");
Helper.GetStudentByID(50);
【问题讨论】:
-
如果您需要能够检索特定项目,ConcurrentBag 绝对不是正确的数据结构。你是如何使用它的?我们需要更多详细信息才能为您提供帮助。
-
@ThomasLevesque 我基本上把它当作一个列表。在 ConcurrentBag 中执行 LINQ,例如 Where、Count、FirstOrDefault。这就是我需要的,一个内存列表,可以为应用程序的其余部分提供服务。
-
我的问题是你为什么使用 50+ 线程?我无法想象这么多设备的速度会有所提高——实际上恰恰相反。
-
@Enigmativity 我没有偏离默认值。这正是调试诊断所说的。
-
@bladefist - 我看不出你的回答是如何回答我的问题的。
标签: c# multithreading linq concurrency concurrentdictionary