创建一个 returns 立即确定的异步控制器
Creating an asynchronous controller that returns OK immediately
我正在尝试将新的 async/await 功能与 webapi 相结合。
我想做的是:
- 我在某个端点的控制器 (A) 上收到 (POST) 请求。
- 这个控制器什么都不做,只是将这个请求发送到另一个端点上的第二个控制器 (B)(不要问我为什么 - 只是一个思想实验)。
- 假设 B 做了一些长时间的 运行 工作(从某处检索数据)并将结果存储在数据库中。
我不想等待 B 的工作,然后才能return 向发送给 A 的请求发送 OK 消息。我希望能够致电 A 并得到 OK 回复在 B 上的工作仍在完成时尽快完成。
这可能吗?如果是这样,设计这样的东西的正确方法是什么?
感谢您的指点。
您可能想用 response code of 202 (accepted) 来响应调用者,以向客户端表明正在进行其他一些处理。
然后,如果您的客户需要额外的反馈,它可以进行长时间的轮询,或者您可以实施 websocket 等。
您想要的是在您的通话中触发 "Fire and Forget" 语义。
如果您使用的是 .NET 4.5.2,则可以使用 HostingEnvironment.QueueBackgroundWorkItem
在 ASP.NET 线程池线程上注册和排队工作。
如果您使用的是以前的版本,则可以使用 Stephan Cleary 的 BackgroundTaskManager
。
请注意,这与 async-await
无关。
示例如下所示:
public HttpResponseMessage Foo()
{
HostingEnvironment.QueueUserWorkItem(() => { /* offloaded code here */ });
return Request.CreateResponse(HttpStatusCode.OK);
}
只是基于 John Skeet 解释的 async/await 概念的假设。 async/await 模式使用维护状态机的延续。基本上框架应该执行指令直到同步方法结束。
当它遇到异步调用指令时,它会调用它,如果结果很容易获得,则进入下一步并进行处理。如果它在调用后没有立即得到结果,它 return 将从方法返回,让框架处理这个问题。所以在你的情况下,我认为如果你没有代码,它实际上会立即 return 。但是如果你有任何长 运行 代码,它应该 return 将工作留给后台框架线程,但结果可能会稍后返回。
如果您的 objective 是为了确保您不会阻挡前景,那么这将通过第一个控制器本身来实现。但即使在你的情况下,第二个控制器也不会阻止 UI。对于您关于这是对还是错的问题,我敢肯定,因为您可能出于某些原因会想到这种模式。
这里高手云集。如果我的解释有误,请纠正我:)
您启动后台工作并立即响应。异步模式仅在您必须以任何方式响应长 运行 任务的结果并防止阻塞调用线程的情况下使用。
即:
public bool ControllerAMethod(byte[] somedata)
{
Task.Factory.StartNew(() =>
{
ControllerB.SendData(somedata);
});
return true;
}
我正在尝试将新的 async/await 功能与 webapi 相结合。
我想做的是:
- 我在某个端点的控制器 (A) 上收到 (POST) 请求。
- 这个控制器什么都不做,只是将这个请求发送到另一个端点上的第二个控制器 (B)(不要问我为什么 - 只是一个思想实验)。
- 假设 B 做了一些长时间的 运行 工作(从某处检索数据)并将结果存储在数据库中。
我不想等待 B 的工作,然后才能return 向发送给 A 的请求发送 OK 消息。我希望能够致电 A 并得到 OK 回复在 B 上的工作仍在完成时尽快完成。
这可能吗?如果是这样,设计这样的东西的正确方法是什么?
感谢您的指点。
您可能想用 response code of 202 (accepted) 来响应调用者,以向客户端表明正在进行其他一些处理。 然后,如果您的客户需要额外的反馈,它可以进行长时间的轮询,或者您可以实施 websocket 等。
您想要的是在您的通话中触发 "Fire and Forget" 语义。
如果您使用的是 .NET 4.5.2,则可以使用 HostingEnvironment.QueueBackgroundWorkItem
在 ASP.NET 线程池线程上注册和排队工作。
如果您使用的是以前的版本,则可以使用 Stephan Cleary 的 BackgroundTaskManager
。
请注意,这与 async-await
无关。
示例如下所示:
public HttpResponseMessage Foo()
{
HostingEnvironment.QueueUserWorkItem(() => { /* offloaded code here */ });
return Request.CreateResponse(HttpStatusCode.OK);
}
只是基于 John Skeet 解释的 async/await 概念的假设。 async/await 模式使用维护状态机的延续。基本上框架应该执行指令直到同步方法结束。
当它遇到异步调用指令时,它会调用它,如果结果很容易获得,则进入下一步并进行处理。如果它在调用后没有立即得到结果,它 return 将从方法返回,让框架处理这个问题。所以在你的情况下,我认为如果你没有代码,它实际上会立即 return 。但是如果你有任何长 运行 代码,它应该 return 将工作留给后台框架线程,但结果可能会稍后返回。
如果您的 objective 是为了确保您不会阻挡前景,那么这将通过第一个控制器本身来实现。但即使在你的情况下,第二个控制器也不会阻止 UI。对于您关于这是对还是错的问题,我敢肯定,因为您可能出于某些原因会想到这种模式。
这里高手云集。如果我的解释有误,请纠正我:)
您启动后台工作并立即响应。异步模式仅在您必须以任何方式响应长 运行 任务的结果并防止阻塞调用线程的情况下使用。 即:
public bool ControllerAMethod(byte[] somedata)
{
Task.Factory.StartNew(() =>
{
ControllerB.SendData(somedata);
});
return true;
}