Асинхронные проблемы с фоновыми задачами в цикле
Я столкнулся с проблемой, касающейся инициализации фоновых задач в цикле в asp.net MVC.
Мой контекст связан с соревнованиями. Соревнование может начаться, как только число участников будет достигнуто, или после задержки. Пользователь выбирает, в скольких соревнованиях он хочет участвовать (vm.InscriptionsNumber
), а затем вызывает следующее Compete
метод.
Если нет никакого существующего соревнования, к которому он может присоединиться, я должен создать его и инициализировать таймер этого нового соревнования, TryStartCompetition
, При вызове этот метод проверяет, началось ли соревнование (потому что число участников было достигнуто), и, если нет, вызывает StartCompetition
метод.
[HttpPost]
public async Task<ActionResult> Compete(CompetitionsViewModel vm)
{
for (int i = 0; i < vm.InscriptionsNumber; i++)
{
Competition competition = UnitOfWork.CompetitionRepo.Get(...);
if (competition == null) // If there is no existing competition the user can join
{
// Create a new one
competition = new Competition(...);
await UnitOfWork.CompetitionRepo.AddOrUpdate(competition);
// Initialize the start max delay
HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken =>
{
await Task.Delay(Competition.Delay);
await TryStartCompetition(competition);
});
}
else if (competitorsNumberConditionOk)
{
await StartCompetition(competition);
}
// Other stuff...
}
await UnitOfWork.Save();
return PartialView("~/Views/Competitions/Index.cshtml", ViewModel);
}
private async Task TryStartCompetition(Competition compet)
{
// Competition has not started yet
if (!compet.StartDate.HasValue)
{
await StartCompetition(compet);
await UnitOfWork.Save();
}
}
private async Task StartCompetition(Competition compet)
{
// Competition ranking calculation and other stuff here needing async calls
compet.StartDate = DateTime.Now;
}
Во-первых await
вызывать StartCompetition
возникает следующее исключение. Я не знаю, как я должен справиться с этим в этом конкретном контексте.
Вторая операция началась в этом контексте до завершения предыдущей асинхронной операции. Используйте 'await', чтобы убедиться, что все асинхронные операции завершены, прежде чем вызывать другой метод в этом контексте. Любые члены экземпляра не гарантированно являются потокобезопасными.
Если vm.InscriptionsNumber
равно 1, все в порядке, но как только появляется цикл, появляется ошибка.
Если кто-нибудь может помочь мне понять, почему это происходит, я был бы очень благодарен.