I have a ConcurrentBag in .Net 4.5 which I am storing about 4,000 rows from a database. I'm storing the DTOs.
My entire application relies on this. I have functions that return the entire list, and also have functions that return a single item. So many places in my code I am doing LINQ queries on the collection, etc.
I pushed it all to production, on site that gets considerable traffic, and immediately 100% cpu. I used the iis diagnostic tool, and sure enough, there were 50+ threads in a deadlock, waiting on the ConcurrentBag.
The documentation says this collection is thread-safe, but either that's not true, or the performance of this collection is not good thusly making it not thread-safe indirectly.
This collection unfortunately isn't read only. If one of the functions that looks up by ID returns null, it will hit a web service, and add it.
I also converted it to a ConcurrentDictionary, and had the same problem. Locks for Days on the .Values property.
What is the fastest and most thread-safe solution in most extreme scenarios?
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...
}
Example usage - Littered throughout the app.
Helper.GetStudents().FirstOrDefault(x => x.name == "foo" && x.status == "bar");
Helper.GetStudentByID(50);