Я не уверен, правильно ли я все делаю.
Справочная информация: у меня есть действие контроллера GET foo () в качестве примера.Этот foo () должен пойти и вызвать bar (), а bar () может занять много времени.Итак, Мне нужно, чтобы foo () ответила «ОК» до (или независимо от того, когда) выполнения bar () .
Небольшая сложность заключается в том, что bar () требуется для доступа к DBContext.и получить некоторые данные из БД.В моей текущей реализации я получаю исключение «DBContext System.ObjectDisposed», когда пытаюсь получить доступ к БД через панель.Любые идеи, почему и как я могу обойти это, пожалуйста?Я действительно новичок в многопоточности и задачах, так что я могу полностью понять, что это неправильно!
Я использую внедрение зависимостей, чтобы предоставить контекст БД при запуске
services.AddEntityFrameworkNpgsql()
.AddDbContext<MyDBContext>()
.BuildServiceProvider();
Затем я вызываю foo() который в свою очередь вызывает bar () с использованием нового потока (возможно, я делаю это неправильно?):
public async Task<string> foo(string msg)
{
Thread x = new Thread(async () =>
{
await bar(msg);
});
x.IsBackground = true;
x.Start();
return "OK.";
}
Таким образом, bar немедленно пытается получить доступ к DBContext, чтобы получить некоторые объекты, и выдает исключение!
Необработанное исключение: System.ObjectDisposedException: Невозможно получить доступ к удаленному объекту.Распространенной причиной этой ошибки является удаление контекста, который был разрешен путем внедрения зависимости, а затем попытка использовать тот же экземпляр контекста в другом месте вашего приложения.Это может произойти, если вы вызываете Dispose () для контекста или заключаете контекст в оператор using.Если вы используете внедрение зависимости, вы должны позволить контейнеру введения зависимости позаботиться об удалении экземпляров контекста.Имя объекта: 'MyDBContext'.
Если я возьму bar () из потока, это нормально, но, конечно, "OK" не возвращается, пока bar не завершит очень длинный процесс, что является проблемой, которая мне нужначтобы обойти.
Большое спасибо за руководство, пожалуйста.
РЕДАКТИРОВАТЬ с рабочим кодом, НО он все еще ожидает завершения Task.Run перед возвратом "ОК".(почти нет?)
public async Task<string> SendBigFile(byte[] fileBytes)
{
ServerLogger.Info("SendBigFile called.");
var task = Task.Run(async () =>
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var someProvider = scope.ServiceProvider.GetService<ISomeProvider>();
var fileProvider = scope.ServiceProvider.GetService<IFileProvider>();
await GoOffAndSend(someProvider, fileProvider, fileBytes);
}
});
ServerLogger.Info("Hello World, this should print and not wait for Task.Run."); //Unfortunately this is waiting even though GoOffAndSend takes at least 1 minute.
return "Ok"; //This is not returned until Task.Run finishes unfortunately... how do I "skip" to this immediately?
}
private async Task GoOffAndSend(ISomeProvider s, IFileProvider f, byte[] bytes)
{
// Some really long task that can take up to 1 minute that involves finding the file, doing weird stuff to it and then
using (var client = new HttpClient())
{
var response = await client.PostAsync("http://abcdef/somewhere", someContent);
}
}