Я столкнулся с проблемой, как инициализировать фоновые задачи в цикле в 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
возникает следующее исключение. Я не знаю, как мне поступить в данном конкретном случае.
Вторая операция началась в этом контексте до завершения предыдущей асинхронной операции. Используйте «ожидание», чтобы убедиться, что все асинхронные операции завершены, прежде чем вызывать другой метод в этом контексте. Любые члены экземпляра не гарантируют потокобезопасность.
Если vm.InscriptionsNumber
равно 1, то все в порядке, но как только возникает петля, появляется ошибка.
Если кто-нибудь может помочь мне понять, почему это происходит, я был бы очень благодарен.
await
, который вызывает исключение, является простымAdd
, я где-то выполняю ленивую загрузку? - person Flash_Back   schedule 22.04.2016for
и второй.UnitOfWork
инициализируется один раз в конструкторе контроллера. Должен ли я тогда удалить его и воссоздать в конце циклаfor
? - person Flash_Back   schedule 22.04.2016QueueBackgroundWorkItem
для вызоваUnitOfWork.Save
в фоновом потоке, а также вызываетеUnitOfWork.Save
в потоке запроса контроллера. Контексты EF не могут использоваться одновременно несколькими потоками. - person Stephen Cleary   schedule 22.04.2016d.moncada
, но я не совсем уверен, где мне следует размещать контекст или выполнятьusing
, поэтому у меня много проблем с объектами, присоединенными дважды и т. д. - person Flash_Back   schedule 22.04.2016