Выполните задачу в действии, не ожидая - задача отменяется - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть асинхронное действие c, которое завершает задачу, которую мне нужно ждать перед возвратом ответа клиенту, но также и задачу, которую я хочу выполнить, но мне плевать на результат.

[HttpPost]
[Route("api/update")]
public async Task Update(Competence competence)
{            
    await _competenceService.Update(competence);
    _userService.DoNotWaitForMe(competence.Year);
}

Оба класса _competenceService и _userService вводятся в контроллер как Scoped через DI, и оба его метода доступны. Я также использую платформу Entity и внедряю контекстный класс

// Startup.cs
services.AddScoped<ICompetenceService, CompetenceService>();
services.AddScoped<IUserService, UserService>();
services.AddDbContext<DbContext>(options =>
{
    options.UseSqlServer(Configuration.GetConnectionString("DbContext"));
});

// CompetenceService.cs
async Task Update(Competence competence)

// UserService.cs
async Task DoNotWaitForMe(int Year)

Хотя ожидаемый метод Update завершается, как ожидается (или выдает исключение при исключении), последний никогда не завершается и выдает исключение

System.Threading.Tasks.TaskCanceledException: задача была отменена. в Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsyn c (логические ошибкиExpected, CancellationToken cancellationToken) в Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsyn * 1026OgnationOnationEgnationCoreE c (CancellationToken CancellationToken, булева errorsExpected) при Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsyn c (RelationalCommandParameterObject parameterObject, CancellationToken CancellationToken) при Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.AsyncQueryingEnumerable 1.AsyncEnumerator.MoveNextAsync() at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable 1 источника, CancellationToken CancellationToken) в Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync [TSource] (источник IQueryable`1, CancellationToken cancellationToken)

, а иногда также

System.ObjectDisposedExce ption: Невозможно получить доступ к удаленному объекту. Распространенной причиной этой ошибки является удаление контекста, который был разрешен путем внедрения зависимостей, а затем попытка использовать тот же экземпляр контекста в другом месте вашего приложения. Это может произойти, если вы вызываете Dispose () для контекста или заключаете контекст в оператор using. Если вы используете внедрение зависимостей, вы должны позволить контейнеру внедрения зависимостей позаботиться об удалении экземпляров контекста.

Я бы хотел, чтобы DI (или кто-либо другой ответственный) не отменял задачу и удалял все объекты до этой асин c задача завершена. Есть ли способ?

1 Ответ

0 голосов
/ 08 апреля 2020

Просто вы не можете просто не дождаться задания. Контекст EF имеет ограниченное время жизни: он создается при запуске запроса и удаляется после его завершения. Если вы вернете ответ до того, как работа над контекстом будет завершена, контекст будет удален, и будет выдан ObjectDisposedException.

Практически всегда неправильно ждать задач, особенно в веб-приложении. Это не так же, как фон. Если вы хотите сделать что-то в фоновом режиме, то вам нужно запланировать это на фактический фоновый сервис. Это может быть что угодно на самом деле: отдельный процесс, консольное приложение, функция Azure или размещенная служба. Короче говоря, вам нужно выполнить работу над чем-то, на самом деле предназначенным для обработки задач в фоновом режиме, а не просто запустить и забыть задачу.

...