【问题标题】:ASP.NET Web Api, Database connection in ThreadsASP.NET Web Api,线程中的数据库连接
【发布时间】:2016-01-15 21:17:18
【问题描述】:

我在我的 asp.net 应用程序的线程中使用数据库时遇到问题。 当我想启动我的应用程序时,我想用它启动一个名为“BackgroundWorker”的线程,该线程在后台运行,直到整个应用程序停止。

问题是线程中的 dbContext 存在大量问题。

我尝试在我的 Startup.cs 中的方法“ConfigureServices”或“Configure”中启动 walker,然后在 Walker 的构造函数中初始化 dbContext,就像这样“dbContext = new ApplicationContext()”它告诉我连接未配置,当我尝试在数据库上的 while(true) 队列中操作时。 如果我为 Walker 编写一个自己的控制器,它在他的构造函数中接收一个 ApplicationContext 然后像这样启动一个线程,如果我用 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) 队列中。

我以许多不同的方式尝试了这些和类似的事情,但总是收到类似这两个或数据库连接关闭的异常。

有人可以帮助我并告诉我这是如何工作的吗?

谢谢!

【问题讨论】:

  • 您的“while (true)”代码在哪个方法中?
  • 你为什么要这样做?可能是一种更简单的方法来解决您遇到的任何问题,这使您想尝试在 Web 应用程序中使用这样的线程。一般来说(我的意思是一般来说,这是主观的),这是一个坏主意。
  • 请解释一下这个项目的架构,您的 API 是否支持 Web 应用程序?
  • @GabrielLuci 编辑了我的问题。 whilte(true) 代码在 DoBackGroundWork() 方法中。 Nikki9696:我想要一个线程,每 30 秒在数据库中搜索一次,如果日期已过期,然后发送一封带有链接的电子邮件,指的是数据库中过期的那个 BrianOgden:我是编程初学者,所以我我不确定,你想听什么,但我试试看:我们有一个 asp.net 4.5 mvc 应用程序。与前端的通信是通过后端的 Restful Web Api 控制器和前端的 AngularJS 控制器进行的。我们首先为数据库使用 EntityFramework 7 代码。

标签: c# asp.net asp.net-mvc multithreading


【解决方案1】:

一般来说,Web 应用程序的服务器端多线程并不经常发生,而且在大多数情况下是一个巨大的禁忌。

从概念上讲,您的服务器是“多线程的”,它处理来自客户端/用户/其他服务器的许多 HTTP 请求。对于移动和 Web 架构/设计,您的服务器处理多个请求,而您的客户端正在处理异步调用并处理等待来自长时间运行调用的响应,例如您的 API 方法 StartWorker

考虑一下这种情况,您向 WebAPI 方法StartWorker 发出请求,客户端发出请求正在等待响应,将工作放在另一个线程上什么都不做,因为客户端仍在等待响应。

例如,假设您的客户端是一个带有 Ajax 调用的 HTML 网页。您通过Ajax 调用StartWorker,您将把数据加载到HTML 表格中。从 UX 的角度来看,您会希望在长时间运行的 StartWorker 响应您的 HTML Page Ajax 调用请求时设置一个进度微调器。当StartWorker 响应时,Ajax 调用会加载带有StartWorker 响应的HTML 表。 StartWorker 必须响应数据。如果StartWorker 事先响应,则您必须通过 SignalR 发送推送通知,例如,当其他线程完成并拥有 HTML 表所需的数据时。

希望您看到,从 Ajax 请求/响应的角度来看,对 WebAPI 方法的调用花费了相同的时间,因此在这种最常见的 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 应用程序,如果您使用的是 Sql Azure,您想要使用的是 Azure Automation 或创建一个 Sql Server Job如果您使用 Sql Server 实例作为后端

【讨论】:

  • 感谢您的回答!但是如果不使用线程,您将如何尝试解决我的问题:我想要一些在服务器上永久运行并搜索数据库的进程,日期是否已过期
  • 这将是您正在寻找的 Windows 服务,或者是 Sql Server 作业,可能是 Sql Server 作业,例如每 30 秒运行一次并查询记录,然后您会从Sql Server 作业,例如对 API 的 HTTP 请求,您必须从 API 发送推送通知,例如,通过 SignalR 来更新客户端 UI。或者再次,您需要一个 Windows 服务,同样的场景,Windows 服务查询数据库,在需要时调用您的 API,并向客户端发送通知。
  • 我不知道您是否没有完全理解,我正在尝试做什么或者我没有理解,您的意思是:我不想向客户发送任何东西。即使没有连接客户端,我也只想要查看数据库中的一个表,查看日期是否过期,然后通过 MailMessage 简单地发送邮件。我只是想告诉自己一些关于 Windows 服务的信息,这对于我的目的来说似乎有点过于强大和复杂,将一个简单的 Web 应用程序托管为一个 azure Web 应用程序
  • 是的,一个 Sql Server 作业会很完美,我一直使用它们来处理这种情况,你让作业运行查询并发送电子邮件,Sql Server 作业很容易内置这一切,如果您使用的是 Sql Azure,则可以通过 Azure 自动化进行设置:azure.microsoft.com/en-us/blog/…
  • 你肯定想要一个 Sql Server 作业,或者如果你正在使用 Sql Azure,请使用 Azure 自动化
【解决方案2】:

DbContext 不是线程安全的。您需要从线程内部创建一个新上下文。

public void DoBackGroundWork()
{
    ChronicusContext anotherContext= new ChronicusContext();

    while (true)
    {
       if (anotherContext.PollModels.Any())
       {
          ...
       }
    }
}

【讨论】:

  • 我试过这个,但是我在“if (dbContext.PollModels.Any())”处收到一个“System.NullReferenceException”
  • 你确定你有 'if (dbContext.PollModels.Any())' 而不是 'if (_dbContext.PollModels.Any())' - 注意下划线。您的问题中有下划线,它与传递给您的 DoBackGroundWork 方法的变量不同。
  • 哦,我确实有一个小的字母切换,但我更正了这个问题,现在我收到了这个异常,尝试 Ians 解决方案:“EntityFramework.Core 中发生'System.InvalidOperationException' 类型的未处理异常.dll 附加信息:未配置数据库提供程序。在设置服务时,通过在 DbContext 类或 AddDbContext 方法中覆盖 OnConfiguring 来配置数据库提供程序。"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-26
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-13
  • 2019-03-28
相关资源
最近更新 更多