В продолжение моих последних размышлений о блокировках в 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 — это имена столбцов таблицы данных, которые содержат нужные данные для сопоставления.
Теперь у меня также есть метод класса, который получает строку и возвращает правильное сопоставленное целое число на основе упомянутого словаря.
Я хочу, чтобы этот метод ждал, пока метод обновления завершит свое выполнение, поэтому на первый взгляд можно было бы рассмотреть следующую реализацию:
lock (r_MappingLock)
{
int? retVal = null;
if (i_MapObj.ContainsKey(i_Key))
{
retVal = i_MapObj[i_Key];
}
return retVal;
}
Это предотвратит неожиданное поведение и возврат значения во время обновления словаря, но возникает другая проблема: поскольку каждый поток, выполняющий описанный выше метод, пытается получить блокировку, это означает, что если несколько потоков попытаются выполнить этот метод одновременно, каждому придется ждать, пока предыдущий поток завершит выполнение метода, и попытаться получить блокировку, и это, очевидно, нежелательное поведение, поскольку описанный выше метод предназначен только для целей чтения.
Я думал о добавлении логического члена в класс, для которого будет установлено значение true или false, независимо от того, обновляется ли словарь или нет, и проверять его в методе «только для чтения», но это вызывает другие проблемы, связанные с состоянием гонки...
Любые идеи, как решить это изящно?
Спасибо еще раз,
Майки