В продолжение моих последних размышлений о блокировках в C # и .NET,
Рассмотрим следующий сценарий:
У меня есть класс, который содержит определенную коллекцию (для этого примера я использовал Dictionary<string, int>
), которая обновляется из источника данных каждые несколько минут с использованием определенного метода, тело которого вы можете увидеть ниже:
DataTable dataTable = dbClient.ExecuteDataSet(i_Query).GetFirstTable();
lock (r_MappingLock)
{
i_MapObj.Clear();
foreach (DataRow currRow in dataTable.Rows)
{
i_MapObj.Add(Convert.ToString(currRow[i_Column1]), Convert.ToInt32[i_Column2]));
}
}
r_MappingLock - это объект, предназначенный для блокировки критической секции, которая обновляет содержимое словаря.
i_MapObj - объект словаря
i_Column1 и i_Column2 - это имена столбцов таблицы данных, которые содержат требуемые данные для сопоставления.
Теперь у меня также есть метод класса, который получает строку и возвращает правильный сопоставленный тип int на основе упомянутого словаря.
Я хочу, чтобы этот метод ждал, пока метод refresh завершит свое выполнение, поэтому на первый взгляд можно рассмотреть следующую реализацию:
lock (r_MappingLock)
{
int? retVal = null;
if (i_MapObj.ContainsKey(i_Key))
{
retVal = i_MapObj[i_Key];
}
return retVal;
}
Это предотвратит неожиданное поведение и возврат значения во время обновления словаря, но возникает другая проблема:
Поскольку каждый поток, который выполняет вышеупомянутый метод, пытается получить блокировку, это означает, что, если несколько потоков пытаются выполнить этот метод одновременно, каждый из них должен будет ждать, пока предыдущий поток завершит выполнение метода, и попытаться запросить блокировку, и это, очевидно, нежелательное поведение, поскольку вышеупомянутый метод предназначен только для чтения целей.
Я думал о добавлении логического члена в класс, который будет установлен в true или false, когда словарь обновляется или нет, и проверяет его в методе «только для чтения», но это вызывает другие проблемы, связанные с состоянием гонки. ...
Есть идеи, как решить это изящно?
Еще раз спасибо,
Mikey