Нужно ли использовать блок lock (lockObj) {}, когда я заполняю здесь свой ConcurrentDictionary?Для небольшого фона это будет использоваться в приложении MVC, хотя я подозреваю, что вопрос о сценарии актуален для любого многопоточного приложения.
При поиске в стеке потока я не нашел этого точного сценария.Когда в первый раз запрашивается значение из значения GetOptionById, оно может вызываться двумя отдельными потоками.
1) Было бы целесообразно сделать объекты списка частным статическим значением, которое вы блокируетевокруг в надежде не вызывать базу данных несколько раз, прежде чем заполнить ConcurrentDictionary?
2) Это (# 1 выше) вообще необходимо, или ConcurrentDictionary достаточно умен, чтобы решить это самостоятельно?Заранее спасибо за любой вклад.
public class MyOptions
{
static string GetOptionById(int id)
{
if (options == null || options.Count <= 0)
FillOptionList();
return options[id];
}
static void FillOptionList()
{
List<MyBusinessObject> objects = DataAccessLayer.GetList();
foreach (MyBusinessObject obj in objects)
options.TryAdd(obj.Id, obj.Name);
}
private static ConcurrentDictionary<int, string> options = new ConcurrentDictionary<int, string>();
}
РЕДАКТИРОВАТЬ: Спасибо всем за ваш вклад, это будет более безопасный подход?
public static string OptionById(int id)
{
if (!options.ContainsKey(id))
{
//perhaps this is a new option and we need to reload the list
FillOptionsOrReturn(true /*force the fill*/);
return (!options.ContainsKey(id)) ? "Option not found" : options[id];
}
else
return options[id];
}
private static void FillOptionsOrReturn(bool forceFill = false)
{
List<MyBusinessClass> objectsFromDb = null;
lock (lockObj)
{
if (forceFill || options == null || options.Keys.Count <= 0)
reasons = DataAccessLayer.GetList();
}
if (objectsFromDb != null)
{
foreach (MyBusinessClass myObj in objectsFromDb)
options.TryAdd(myObj.id, myObj.name);
}
}
private static ConcurrentDictionary<int, string> options = new ConcurrentDictionary<int, string>();
private static object lockObj = new object();