我应该如何在ASP.NET 4中执行长时间运行的任务?

时间:2011-04-05 13:54:38

标签: asp.net iis asynchronous asp.net-4.0 azure-webjobs

我正在使用.NET构建一个网站4.有许多MSDN文章可以追溯到2003, about using Thread objects2007, using Asynchronous Pages in .NET 2,但这些文章都很陈旧。我知道.NET 4为我们带来了Task classsome people vaguely cautioning against its use for this purpose

所以我问你,大约2011年在ASP.NET 4中运行IIS下的后台/异步工作的“首选”方法是什么?关于直接使用Thread / Task有什么警告? Async = true还在流行吗?

编辑:好的,好的,从答案中可以清楚地看到,如果可以,我应该提供服务。但是在webapp中执行它的优势非常明显,尤其是更容易部署/重新部署。假设这个过程是安全崩溃的,那么,如果我在IIS中做这个,那么最好的方法是什么?

6 个答案:

答案 0 :(得分:17)

优先避免在这样的环境中执行长任务。

通过互操作性将长时间运行的任务委派给稳定的系统服务,使Web应用程序保持响应,并且只需要直接用户请求。

Web应用程序从来没有(现在仍然没有)被认为是可靠的系统 - 任何曾经使用过浏览器的人都会遇到(至少)超时,这是肯定的;这种不便(对双方而言)不仅限于这种情况。当然,任何系统都可能崩溃,但在系统内置为持久性的情况下,这种事件的情况应该是完全特殊的。

Windows服务旨在长期运行,如果出现问题,您通常会比您的个人服务更担心。

答案 1 :(得分:2)

最好避免,但如果你被迫,请考虑一下汉塞尔曼在How to run Background Tasks in ASP.NET的想法。

其中,为了快速简便,我建议您特别注意4.5.2中添加的QueueBackgroundWorkItem

从个人经验来看,任务不会削减它。 QueueBackgroundWorkItem要好得多。

答案 2 :(得分:0)

我的首选方法与Robert Harvey在答案中提出的方法相同。

您仍然可以使用Task Parallel Library,但是在IIS之外的单独进程中启动任务(原因是IIS只有有限数量的工作线程可以分发,并施加其他限制,可以使用很长时间运行任务不可预测)。

答案 3 :(得分:0)

您可以使用有限的线程编号(例如仅2)创建一个类似此http://www.dotnetperls.com/threadpool的静态ThreadPool。然后将任务排入其中,但强烈建议不要这样做,因为Web服务器不适用于此类任务

答案 4 :(得分:0)

这是对“每天一次”情景的描述。

如果您真的想避免创建服务,可以每隔1分钟启动一个计时器。每次调用计时器委托时,您都必须运行类似这样的程序(伪代码):

lastInvokeDay = LoadLastInvokeDate();
If (lastInvokeDay < DateTime.Now.Date && timeOfDayToRun == DateTime.Now.Time)
{
  try
  {
    today = DateTime.Now.Date;
    runMyTask();
  }
  catch..
  finally
  {
    lastInvokeDay = today;
    SaveLastInvokeDay(lastInvokeDay);
  }
}

请记住,lastInvokeDay应该保存在数据库或文件中......

现在,如果要立即调用任务,可以根据需要简单地调用runMyTask()。 如果对于让每天多次运行runMyTask非常重要,可以在其中创建一个同步的代码块(使用lock语句)并在其中移动lastInvokeDay检查。

这会回答你的问题吗?

答案 5 :(得分:0)

我可以建议一个简单的解决方案,该解决方案不使用Windows服务,但是能够调用要在IIS沙箱外部执行的任务。 同样,它可以很容易地被任何其他语言或它们的混合采用,在我的例子中是Python

  1. 从PowerShell控制台执行,在IIS服务器上创建事件日志和源(需要管理权限):

    [System.Diagnostics.EventLog]::CreateEventSource('Automations', 'Automations')
    

    如果没有管理权限,请跳过此步骤。您将后退以使用Windows /应用程序日志

  2. 创建要在事件上执行的Task Scheduler任务,例如ID = 2020,Log ='Automations'和Source ='Automations'。在那里,您可以使用所有必要的权限调用任何您喜欢的东西

  3. 在处理Web请求时准备代码以发送事件。给您一个Python示例,但您可以将其用于您的语言:

    import win32evtlog
    app_name = "Automations"
    event_id = 2020
    event_category = 0
    event_type = win32evtlog.EVENTLOG_INFORMATION_TYPE
    messages = ['Starting automation']
    
    # Logs event into the custom Automations log if it exists,
    # otherwise logs event into Windows/Application log
    handle = win32evtlog.OpenEventLog("localhost", app_name)
    win32evtlog.ReportEvent(handle, event_type, event_category, event_id, None, messages, None)
    
  4. 利润