Назад к задачамПолучайте помощь с лайвкодингом в реальном времени с Sobes Copilot
Junior — Senior
12
Обнаружение проблемы синхронизации в многопоточном сервисе
Условие задачи
Дан класс FlatteningService, содержащий несколько полей‑коллекций, в частности Dictionary<string, IList<FlattenLocationFilter>> locationFilters. Внутри метода MakeFlatten происходит чтение и запись в эту словарную структуру. При одновременных вызовах метода из десяти потоков могут возникать исключения типа KeyNotFoundException и другие связанные с доступом к словарю. Важно понять, почему при проверке наличия ключа через ContainsKey и последующем добавлении через Add появляется ошибка «ключ уже существует», а последующее обращение к locationFilters[locationFilter] приводит к KeyNotFoundException. Найдите и опишите источник проблемы.
public class FlatteningService
{
private readonly Dictionary<string, IList<FlattenLocationFilter>> locationFilters;
public PromoFlatteningService()
{
locationFilters = new Dictionary<string, IList<FlattenLocationFilter>>();
}
public IEnumerable<FlattenPromo> MakeFlatten(IEnumerable<OraclePromo> items)
{
var itemsList = items.ToLookup(x => x.PromoCode);
var flatList = new List<FlattenPromo>();
foreach (var src in itemsList.Single())
{
var promoCode = $"{src.PromoCode}";
const string locationFilter = "Auchan";
if (!locationFilters.ContainsKey(locationFilter))
{
// выходит ошибка, что ключ уже существует
locationFilters.Add(locationFilter, new List<FlattenLocationFilter>
{
new()
{
FilterCode = locationFilter,
FilterOperator = "AND",
CriteriaCode = "Location",
CriteriaOperator = "OR",
ExpectedValue = "Auchan",
ExpectedOperator = "EQ",
FilterDescription = "none",
LocationPropertyCode = "none"
}
});
flatlist.Add(new FlattenPromo
{
PromoCode = promoCode,
PromoBegin = src.StartDate.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc),
PromoEnd = src.EndDate.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc),
LocationFilterCode = locationFilter,
LocationFilter = locationFilters[locationFilter], // выходит ошибка keyNotFoundException
ProductCode = src.ProductId,
ProductDiscountPercent = src.DiscountPercent,
ProductPlanQuantity = src.PlanSum,
});
}
}
}
}