我不确定我是否完全正确地处理了这个问题。
背景:我有一个控制器动作GET foo()作为例子。这个foo()需要调用bar(),bar()可能需要很长时间。所以,我需要foo()在bar()完成之前(或无论何时)用“确定”来响应。
稍微复杂一点的是,bar()需要访问DBContext并从数据库中获取一些数据。在我当前的实现中,当我试图通过bar访问数据库时,会出现“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来获取一些实体,并抛出异常!
未处理的异常:系统。ObjectDisposedException:无法访问已处置的对象。此错误的一个常见原因是,处理通过依赖项注入解析的上下文,然后在应用程序的其他地方尝试使用相同的上下文实例。如果对上下文调用Dispose(),或将上下文包装到using语句中,可能会发生这种情况。如果您使用的是依赖项注入,那么应该让依赖项注入容器处理上下文实例。对象名称:“MyDBContext”。
如果我将bar()从线程中取出,这是可以的,但当然,在bar完成其非常长的过程之前,不会返回“OK”,这是我需要解决的问题。
非常感谢一些指导。
使用正在运行的代码进行编辑,但它仍在等待任务。运行以完成,然后返回“确定”(快到了吗?)
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);
}
}
在Asp。net中,注入项的生命周期取决于框架。一旦foo()返回,Asp就不知道您创建的线程仍然需要它提供给您的DbContext,因此Asp会处理该上下文,您就会遇到问题。
您可以自己在线程中创建一个新的DbContext,并决定何时处理它。这并不太好,因为如果您的数据库配置更改,您现在有两个地方可能需要更新。这里有一个例子:
var optionsBuilder = new DbContextOptionsBuilder<MyDBContext>();
optionsBuilder.UseNpgsql(ConnectionString);
using(var dataContext = new MyDBContext(optionsBuilder.Options)){
//Do stuff here
}
作为第二种选择,Asp。net core还可以使用IHostedService
创建后台服务,并在初创企业中注册它们,以及依赖注入。您可以创建一个运行后台任务的后台服务,然后foo()可以将该任务添加到该服务的队列中。这里有一个例子。
AddDbContext
避免该异常的最简单方法是将
API功能更强大,通常性能更好。它看起来是这样的:IServiceScopeFactory
注入控制器,然后使用CreateScope()
创建一个新的作用域,并从该作用域请求MyDBContext
服务(您不需要担心DbContextOptions
)。作业完成后,处理随后处理DbContext
的作用域。与其使用线程
,不如使用任务
<代码>任务
public class ValuesController : ControllerBase
{
IServiceScopeFactory _serviceScopeFactory
public ValuesController(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
public async Task<string> foo(string msg)
{
var task = Task.Run(async () =>
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetService<MyDBContext>();
await bar(db, msg);
}
});
// you may wait or not when task completes
return "OK.";
}
}
你也应该知道,Asp。Net不是执行后台任务的最佳场所(例如,当应用程序托管在IIS中时,可能会因为应用程序池回收而关闭)
你的
服务器记录器。信息(“SendBigFile finished”)
客户端时,code>不会等待。PostAsync
已完成。它在任务之后立即记录。运行
启动新任务。在客户端之后记录它。PostAsync
完成后,您需要放置服务器记录器。信息(“SendBigFile finished”)
紧接着
等待GoOffAndSend(someProvider,fileProvider,fileBytes)
:
...
await GoOffAndSend(someProvider, fileProvider, fileBytes);
ServerLogger.Info("SendBigFile finished.");
...
如何在.NET核心库项目中将一个类注入另一个类?在API项目中的StartUp类ConfigureServices中,我应该在哪里配置DI?
我有一个ASP。NET核心2.1站点,注册了几个DbContext和一些条件连接字符串。 出于调试目的,我想列出所有注册的<code>DbContext</code>及其连接字符串,以确保所有内容都配置良好。 这只是一个“测试”功能,不用于任何其他用途,因此请不要回答“您不应该这样做”、“它是反模式”等。
复合在这种情况下“消耗”一个子对象数组,从某种意义上说,“吸入”用密钥注册的IFoo的每个实现。这是一个重要的方面:如果您要用一个键注册复合,它将尝试实例化自己,并立即导致StackOverflow异常。 本机DI不支持这些命名注册。 这个例子是从这里提取的
我已经找到了几个这样的帖子,但不能确定我在这里做错了什么。 我试着在两张桌子上各放一个项目。第二项包含对第一项的查找。我可以在没有问题的情况下为父级添加种子,但无法找到正确的语法来为子级添加种子。 下面是我用来种子父级的代码 下面是种子子的代码--这将失败: 根据文档的建议,我使用了一个匿名对象,而不是类本身。我也尝试过同时使用navigation属性、外键和nav道具。ID=1的组肯定已经在db
我已经开始涉足ASP. Net Core,并发现依赖注入是ASP. Net Core框架中的一流公民,它是内置的,可以用于注入各种服务和库。 我想知道他们正在使用哪个依赖注入框架。他们的文档介绍了ASP中的依赖项注入。网芯 ASP。NET Core从一开始就被设计为支持和利用依赖注入。ASP。NET核心应用程序可以通过将内置框架服务注入Startup类中的方法来利用这些服务,应用程序服务也可以配置