从Web API Controller启动长时间运行的操作

时间:2014-11-07 07:15:14

标签: c# wcf asp.net-web-api asp.net-web-api2

我将现有的自托管WCF服务移植到IIS托管的Web API。

服务旨在执行长时间运行的操作,客户端(桌面应用程序)可以启动操作,并等待结果,或者断开服务(甚至关闭),然后再返回结果。

目前,WCF服务有此类联系(不允许会话):

public interface IMyServiceContract
{
    // this initiates the action and returns the action id
    int StartAction(ActionParams actionParams);

    // this allows client to query action status (running, completed, faulted)
    ActionStatus GetActionStatus(int actionId);

    // this allows client to download action result, if action was completed
    ActionResult GetActionResult(int actionId);
}

ActionParamsActionResult是一些数据合同,其中包含输入参数和结果值(它不重要,问题上下文中的内容)。

StartAction方法创建操作ID,通过Task.Factory.StartNew启动任务,然后返回。客户端定期轮询服务,调用GetActionStatus方法,如果已完成,客户端将使用GetActionResult下载结果。

注意,该用户可以启动操作,并关闭计算机,运行客户端应用程序, 但后来他可以下载动作结果。

问题。使用Web API执行此类操作的方法是什么?

我已经在SO上阅读了一些问题,并在asp.net上阅读了教程,但是样本构建得非常相似:它们实现了一种等待的方法并调用异步API(例如,来自EF 6)。到目前为止,据我所知,这并不允许场景"断开连接并下载结果"。

此外,Stephen Cleary发表的this帖子说:

  

这就是为什么ASP.NET的一个原则是避免使用线程   池线程(ASP.NET提供给你的请求线程除外)   课程)。更重要的是,这意味着ASP.NET应用程序   应该避免使用Task.Run。

我错过了什么吗?

1 个答案:

答案 0 :(得分:2)

我使用Hangfire.io进行长时间运行的任务。 Hangfire使用数据库并确保执行任务,即使重新启动了网站(或应用程序池)。

它提供了一个非常简单的API:

BackgroundJob.Enqueue(() => LongRunningTask());

它允许您安排后续执行任务或重复执行任务:

BackgroundJob.Schedule(
    () => LongRunningTask(), 
    TimeSpan.FromDays(7));

RecurringJob.AddOrUpdate(
    () => LongRunningTask(), 
    Cron.Daily);

来自其网站的声明:

  

仅在成功执行时才从存储中删除后台作业。应用程序重启后,突然中止的作业将被重新排队   创建作业后,即使主机进程已终止,也至少会执行一次。