유닛 테스트를 하다가 아래와 같은 예외가 발생했습니다.
Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection’s state is no longer correct.
관련해서 구글에 검색해보니 원인이 명확하지 않은 것 같습니다.
문제가 발생한 유닛테스트 메서드는 아래와 같습니다. NUnit을 통해 작성되었고, 처음보는 클래스는 자체 제작 클래스라고 보시면 될 듯 합니다.
[TestCase(419364050, EShopeeItemStatus.NORMAL)]
[TestCase(419364050, EShopeeItemStatus.UNLIST)]
public async Task InitGmarketWhiteList(long shopId, EShopeeItemStatus eShopeeItemStatus)
{
RequestGetItemList req = new()
{
ShopId = shopId,
PartnerId = _shopeeOption.PartnerId,
Offset = 0,
PageSize = 100,
UpdateTimeFrom = new DateTimeOffset(DateTime.Now.AddYears(-3)).ToUnixTimeSeconds(),
UpdateTimeTo = new DateTimeOffset(DateTime.Now.AddDays(1)).ToUnixTimeSeconds(),
ItemStatus = eShopeeItemStatus
};
TaskBase<ResponseGetItemBaseInfo> taskBaseRes = await req.FullBaseInfoScanAsync(_shopeeClient);
if (!taskBaseRes.IsSuccess)
{
Assert.False(!taskBaseRes.IsSuccess);
}
ResponseGetItemBaseInfo res = taskBaseRes.Result;
AwesomeSwagClient awesomeSwagClient = new(new HttpClient(), _companyId);
SemaphoreSlim semaphore = new(20);
List<Task> tasks = new();
foreach (ResponseGetItemBaseInfo._Item item in res.ItemList)
{
tasks.Add(Task.Run(async () =>
{
await semaphore.WaitAsync();
try
{
Product awesomeSwagSourceItem = await awesomeSwagClient.GetProductFromOrgIdDetailAsync(item.ItemSku);
if (awesomeSwagSourceItem is null)
{
EcWhiteList reqWhiteList = new()
{
Platform = EPlatform.SHOPEE,
PlatformId = item.ItemId.ToString(),
ShopId = shopId.ToString(),
ShopName = string.Empty,
};
await _ecWhiteListService.InsertAsync(reqWhiteList); // 예외 발생지점
}
}
finally
{
semaphore.Release();
}
}));
}
await Task.WhenAll(tasks);
Assert.True(true);
}
public async Task InsertAsync(EcWhiteList edata)
{
try
{
_context.EcWhiteLists.Add(edata);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
}
}
문제가 발생한 메서드는 주석으로 표기했고 메서드의 정의는 아래 InsertAsync 메서드입니다.
Cosmos DB에 Semaphore를 활용하여 웹통신한 결과를 저장하는 코드인데 이런 에러가 발생합니다…
물론 병렬처리없이 동기식으로 foreach문에서 하나씩 돌리면 문제가 발생하지 않습니다.
왜 발생하는 걸까요?