在ASP.NET进程中运行长时间的代码

5
例如,我们在ASP.NET表单的代码后端中使用此代码:
private void btnSendEmails_OnClick()
{
    Send100000EmailsAndWaitForReplies();
}

这段代码的执行将因为超时原因被终止。 为了解决这个问题,我希望看到类似这样的东西:

private void btnSendEmails_OnClick()
{
    var taskId = AsyncTask.Run( () =>  Send100000EmailsAndWaitForReplies() );
    // Store taskId for future task execution status checking.
}

这种方法将在w3wp.exe进程之外的某些特殊环境中执行。

有人知道解决此类问题的框架/工具集吗?

更新:电子邮件发送方法只是我所说的例子。实际上,我可能有很多需要在asp.net工作过程之外执行的功能。

例如,对于从几个第三方服务聚合数据并对其进行处理后发送回另一个服务的应用程序来说,这一点非常重要。


1
如果您可以在90秒的时间限制内完成,您可以使用QueueBackgroundWorkItem。其他选项包括HangFire、Web Jobs和Azure云服务。有关更多详细信息,请参见下面的答案。 - RickAndMSFT
9个回答

5

这个问题已经在其他问题中讨论过:

ASP.NET中的多线程

ASP.NET中的BackgroundWorker线程

没有好的方法来做到这一点。您不希望在ASP.NET工作进程中运行任何长时间运行的进程,因为它可能在您完成之前进行回收。

编写一个后台运行的Windows服务来为您执行工作。将消息放入MSMQ以启动任务。然后它们可以运行任意长时间。


1
Windows服务如何知道我的业务对象? - Ewerton

3

1
ASP.NET托管环境对于任何长时间运行的进程,无论是CPU还是I/O消耗,都非常危险,因为可能会发生突然的AppDomain卸载。
如果想在请求处理管道之外执行后台任务,请考虑使用http://hangfire.io,它可以为您处理所有后台处理的困难和风险,而无需安装其他Windows服务(但在必要时也可以使用它们)。这里也有一个邮件发送教程

1

我可以想到两种可能的方案:

  1. 您可以创建一个Windows服务,托管一个远程对象,并让您的Web应用程序调用该远程对象,以确保方法在IIS进程空间之外执行。
  2. 您可以设置一个数据库或MSMQ,记录请求。然后,您的Web应用程序可以监视请求的状态,随后通知用户其完成情况。我会设想一个服务来完成这些请求。

0

当你的网站由共享主机提供商托管时,运行自定义 Windows 服务通常是不可能的。运行一个单独的线程并将其置于睡眠状态以在常规间隔运行可能不一致,因为 IIS 将倾向于定期回收您的线程,即使通过代码或配置文件设置脚本执行属性也不能保证您的线程不会被杀死和回收。

我发现了一种基于缓存过期的方法,考虑到共享托管服务提供的方法,这可能是最安全、最一致的选择。本文很好地解释了这一点,并提供了一个作业队列类来帮助管理您计划中的作业,请在文章末尾查看 - http://www.codeproject.com/KB/aspnet/ASPNETService.aspx


0

一种选项是让任务执行一定数量的电子邮件,然后 Response.Redirect 返回其本身并重复此过程,直到您发送所有电子邮件为止。


0
你可以将发送邮件的功能作为服务运行。将请求提交给它,让它处理。定期查询其状态。如果你控制服务器,可以安装一个 Windows 服务,这可能是最理想的处理和生命周期管理方式。

0
ASP.NET 2.0+支持异步页面的概念。在您的页面中添加页面指令Async="true"。
然后在Page_Load中,使用BeginEventHandler和EndEventHandler委托,在相应的“处理程序”中异步执行代码。
<%@ Page Language="C#" Async="true" %>
<script runat="server">

  protected void Page_Load(object sender, EventArgs e)
  {
    BeginEventHandler begin = new BeginEventHandler(BeginMethod);
    EndEventHandler  end = new EndEventHandler(EndMethod);

    AddOnPreRenderCompleteAsync(begin, end);
  }
</script>

-4

服务器.ScriptTimeout = 360000000;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接