我在asp.net应用程序的线程中使用数据库时遇到问题。 当我想启动我的应用程序时,我想启动一个名为" BackgroundWorker"用它,它在后台运行,直到整个应用程序停止。
问题是我在线程中遇到了dbContext的大量问题。
我尝试在方法" ConfigureServices"中的Startup.cs中启动walker。或"配置"然后在Walker的构造函数中初始化dbContext,就像这样" dbContext = new ApplicationContext()"它告诉我,当我尝试在数据库上的while(true)队列中操作时,没有配置连接。 如果我为Walker编写一个自己的Controller,它在构造函数中接收一个ApplicationContext然后启动这样的Thread,如果我用GET请求调用一次这个控制器:
public BackgroundWorker(ChronicusContext dbContext)
{
_dbContext = dbContext;
_messageService = new MailMessageService();
}
// GET: api/backgroundworker
[HttpGet]
[Route("start")]
public void StartWorker()
{
//Thread thread = new Thread(this.DoBackGroundWork);
Thread thread = new Thread(() => DoBackGroundWork(this._dbContext));
thread.Start();
}
public void DoBackGroundWork(ChronicusContext _dbContext)
{
while (true)
{
if (_dbContext.PollModels.Any()) //Here is the exception
{
...
}
}
}
然后我收到一个System.ObjectDisposedException,该对象已经放在while(true)队列中。
我以许多不同的方式尝试了这些和类似的东西,但总是收到像这两个例外或数据库连接关闭的异常。
有人可以帮我告诉我,这是怎么回事?
谢谢!
答案 0 :(得分:3)
通常,Web应用程序的服务器端多线程不会经常发生,并且大多数情况下都是不可能的。
从概念上讲,您的服务器是"多线程",它处理来自客户端/用户/其他服务器的许多HTTP请求。对于移动和Web架构/设计,您的服务器处理多个请求,您的客户端正在处理异步调用,并处理等待API方法StartWorker
等长时间运行调用的响应。
想想这个场景,你向WebAPI方法StartWorker
,客户端发出请求,让请求等待响应,将工作放在另一个线程上什么都不做,因为客户端仍在等待响应。
例如,让我们将您的客户端视为带有Ajax调用的HTML网页。您通过StartWorker
致电Ajax
,您将把数据加载到HTML表格中。从UX的角度来看,您希望在长时间运行StartWorker
响应HTML页面Ajax调用请求时设置进度微调器。当StartWorker
响应时,Ajax调用会加载带有StartWorker
响应的HTML表。 StartWorker
必须回复数据。如果StartWorker
事先响应,则必须通过SignalR发送推送通知,例如,当另一个线程完成并拥有HTML表所需的数据时。
希望您看到,对WebAPI方法的调用从Ajax请求/响应角度来看需要相同的时间,因此多线程在这种情况下变得毫无意义,这是一种最常见的Web应用程序方案。
您可以让客户端UI加载其他UI元素,在HTML表UI区域中显示进度微调器,直到数据库调用完成并响应Ajax调用的数据。通过这种方式,您的用户知道事情正在发生,而且仍在加载某些内容。
如果您的API中仍需要额外的线程以满足您的项目需求,我相信您必须使用Entity Framework 6或更高版本来支持异步查询,请参阅本教程:
http://www.codeproject.com/Tips/805923/Asynchronous-programming-in-Web-API-ASP-NET-MVC
<强>更新强>
现在我知道您需要在重复的时间内运行SQL查询,并且您有一个Azure Web App,如果您使用的是Sql Azure或创建一个Azure Automation,那么您要使用的是Sql Server Job {3}}如果您使用Sql Server实例作为后端
答案 1 :(得分:1)
DbContext不是线程安全的。您需要从线程内部创建一个新的上下文。
public void DoBackGroundWork()
{
ChronicusContext anotherContext= new ChronicusContext();
while (true)
{
if (anotherContext.PollModels.Any())
{
...
}
}
}