【问题标题】:Start long-running action from Web API Controller从 Web API 控制器开始长时间运行的操作
【发布时间】:2014-11-07 16:25:34
【问题描述】:

我正在将现有的自托管 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。

我错过了什么吗?

【问题讨论】:

  • “我错过了什么吗?”是的。 IIS 不应用于长时间运行的进程。 IIS(用于性能)旨在终止与请求不直接关联的任何线程。这意味着它不能运行长时间运行的进程*。这可能是应用程序一开始是自托管服务的最初原因。 (* 可以做到,但非常困难weblog.west-wind.com/posts/2013/Oct/02/…)。
  • 老实说,正确的实现是在 MQ 上使用 WCF(请注意 MSMQ 非常垃圾)。
  • 您可以使用 IIS 的 AppFabric 扩展,它可以让您在 IIS 中运行长时间运行的任务。实际上,如果您的 WCF 服务托管在 IIS 中,您也应该使用 AppFabric
  • @Uriil 是正确的。您要实现的称为 ESB,AppFabric 是它的 MS.Net 版本。自己滚动时会遇到很多问题。 Vanilla WCF SOAP 是一种无状态协议,要让它发挥作用将非常困难。
  • @Uriil:我的 WCF 服务是自托管的,这就是附加线程没有问题的原因。我会看看 AppFabric,谢谢。

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


【解决方案1】:

我正在使用Hangfire.io 处理长时间运行的任务。 Hangfire 使用数据库并确保执行任务,即使网站(或应用程序池)重新启动也是如此。

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

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

它允许您安排任务以便稍后执行或重复执行:

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

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

来自他们网站的声明:

只有在成功执行后才会从存储中删除后台作业。应用程序重新启动后,突然中止的作业将重新排队。
一旦一个作业被创建,它至少会被执行一次,即使宿主进程被终止了。

【讨论】:

  • 谢谢,看起来很有希望。
猜你喜欢
  • 2012-04-03
  • 1970-01-01
  • 2016-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多