所以我尝试使用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;
}
答案 0 :(得分:3)
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。