【问题标题】:REST-Call with async server implementation带有异步服务器实现的 REST-Call
【发布时间】:2022-02-02 15:10:35
【问题描述】:

在我的应用程序中,我有一个服务器,它提供了一个 REST-Api,我的 UI 可以与之通信。

现在我必须在服务器上启动一个长时间运行的进程,但我希望客户端不要等待服务器的响应。

我知道我可以直接触发并忘记调用后而不等待响应,但我需要在客户端知道服务器上的进程已正确启动。

所以我想到了以下几点:

[HttpPost]
[Route("startscan")]
public HttpResponseMessage StartScan()
{
  Task.Factory.StartNew( () =>
  { 
    //Do long running things here 
  }); 
  return Request.CreateResponse(HttpStatusCode.OK);
}

所以我现在的问题是:我开始的任务会执行到底吗?问题的背景是,据我所知,每次调用都会创建一个控制器实例。因此,控制器的实例会在请求完成时终止,还是我开始的任务会运行到它结束。该任务有时可能需要 10 分钟或更长时间。

【问题讨论】:

  • 对于每个请求,当响应完成时,您只会得到一个响应。您需要两个请求/响应。第一个请求将开始处理。第二个请求将返回响应结果。
  • 我不需要这个请求的响应。为此,我有另一种方法。我只想完成第一个请求并让任务运行
  • 好吧,如果您的控制器有任何依赖项用于继承您的任务;当控制器被处理时,正在运行您的任务的依赖项将不会存在,因此您的工作可能没有完成。
  • 所以(对不起两行)你需要在一个新的单例服务中保持依赖项

标签: c# rest controller task


【解决方案1】:

一种简单的方法是只使用异步方法而不等待任务结果,如下所示:

[HttpPost]
[Route("startscan")]
public async HttpResponseMessage StartScan()
{
  DoLongRunningThings();
  return Request.CreateResponse(HttpStatusCode.OK);
}

public async Task DoLongRunningThings()
{
  // Do Stuff here
}

但是,如果您的处理更复杂并且需要更大的弹性,您应该研究如何使用后台作业。以下是您可以使用的很好的集合:https://stackoverflow.com/a/36098218/16154479

【讨论】:

    【解决方案2】:

    我开始的任务会执行到底吗?

    可能是,但也可能不是。有时它不会完全执行。这是滥用 ASP.NET 应用程序(处理 HTTP 请求)作为后台服务(在请求上下文之外运行)的结果。

    有一个最佳实践可以避免可能的部分执行:distributed architecture(正如我在博客中描述的那样)。这个想法是您的控制器将描述要完成的工作的消息排入持久队列,然后返回。然后有一个单独的后台服务从队列中读取并执行实际工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-25
      • 2014-11-09
      • 1970-01-01
      • 1970-01-01
      • 2016-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多