【问题标题】:How do I spawn a task that will run to completion and immediately return to the client?如何生成一个将运行完成并立即返回给客户端的任务?
【发布时间】:2014-09-30 22:38:29
【问题描述】:

所以我正在尝试使用 HTTP 202 代码为服务器端异步创建概念证明(服务器接受任务,立即返回一个端点进行轮询,然后创建/更新资源)

Rick Strahl has a description 在普通的 ASP.NET 中如何做到这一点。该技术取决于能够 Response.End 然后继续执行代码。 Response 对象在 Web API 控制器的上下文中似乎不可用。

如果下面的工作按计划进行,它不会阻止返回 http 202 并且仍然保证数据库任务将运行完成。

//Insert or Update Asych. 
public Task<HttpResponseMessage> Post(bool asynch, [FromBody]DatedValue value) //Insert Value
{
    Guid key = Guid.NewGuid();

    //Want this to run to completion, even if response associated with parent thread is done.
    Task toWait = Task.Factory.StartNew(() =>
    {
        queue.Add(key, 0);
        DatedValue justCreated = Insert(value);
        queue[key] = justCreated.Id;
    });

    //Return address to resource just created.
    Task<HttpResponseMessage> sender = Task.Factory.StartNew(() =>
    {
        HttpResponseMessage message = Request.CreateResponse(HttpStatusCode.Accepted);
        message.Headers.Location = new Uri("/ValueQueue/" + key);
        return message;
    });

    Task.WaitAll((new[] { toWait, sender }));

    return sender;
}

【问题讨论】:

  • 您的问题是什么?给我测试一下?再写一个?
  • 如何生成一个将运行完成并立即返回(响应)给客户端的任务?用英语简短描述模式就可以了。我实际上并不信任多线程代码的测试,nunit 主机的行为与 ASP.NET 主机完全不同。
  • 您的代码无法实现您的目标。您正在阻止 Task.WaitAll,因此在 两个 任务完全完成之前,您的方法无法完成。从事物的声音来看,您真正想要的是“事后”逻辑的即发即弃(未观察到)任务,但 ASP.NET 如何处理即发即弃任务以及它是否会保证它们将运行完成即使在发送响应之后 - 我也不知道(更不用说这听起来像是一个非常糟糕的主意)。

标签: c# asp.net-web-api task-parallel-library


【解决方案1】:

Task.WaitAll 阻止执行并且在两个任务都完成之前不会返回响应。如果您更改代码,如下所示,您应该能够在任务运行时返回响应。

public HttpResponseMessage Post(bool asynch, [FromBody]DatedValue value)
{
    Guid key = Guid.NewGuid();

    Task.Factory.StartNew(() =>
    {
        queue.Add(key, 0);
        DatedValue justCreated = Insert(value);
        queue[key] = justCreated.Id;
    });

    HttpResponseMessage message = Request.CreateResponse(HttpStatusCode.Accepted);
    message.Headers.Location = new Uri("/ValueQueue/" + key);
    return message;
}

但是,您应该意识到这种方法存在的问题。如果您在 IIS 上托管 Web API,则您的工作进程可能会在您的任务运行时被回收。由于您已经返回了响应,因此就 ASP.NET 而言,它已经完成了它的工作。因此,如果出于某种原因 IIS 决定回收工作进程,无论您的任务在哪里执行,它都会继续执行,因此您最终可能会收到损坏的数据。

在 .NET 4.5.2 中,您可以使用 QueueBackgroundWorkItem。阅读这个 - http://blogs.msdn.com/b/webdev/archive/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-long-background-process-in-asp-net.aspx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    • 1970-01-01
    • 2015-08-22
    • 1970-01-01
    相关资源
    最近更新 更多