【发布时间】: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);
}
ActionParams 和ActionResult 是一些数据协定,其中包含输入参数和结果值(没关系,在问题的上下文中是什么)。
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