我们有一个ASP.NET MVC 3应用程序,它与服务逻辑的WCF层交互。在一个特定功能上,服务层需要很长时间才能响应,在svc上的UI超时。 处理本身是巨大的,因此它需要花费更多的时间。我们不希望用户看到超时,,因此我们计划显示部分成功状态,并继续更新处于状态的用户界面。
我们计划将流程分为不同的步骤,其中一些步骤是 fire and forget fashion 。现在当用户请求细节时
Svc处理强制性步骤,返回回复
Svc还启动一个任务使用下面的(TPL)触发它,执行非强制性步骤
Task.Factory.StartNew(FireAway);
用户界面保持轮询以更新状态
任务更新DB中的完成状态
UI轮询并检索完成状态并显示在UI
关注...
答案 0 :(得分:1)
首先创建
Task.Factory.StartNew(FireAway);
您没有显式创建新线程。该任务将使用线程池中的线程,但是从任务到线程没有1:1的映射。例如,如果您的任务将花费很长时间来执行I / O操作,那么基础线程可以被另一个请求使用。
如果您已完成所有操作,则您指定的设计不应导致任何资源(线程或内存)泄漏。从技术角度来看设计是正确的,但可以大大改进。
此设计很容易导致IIS重新启动,从而在运行中阻止此任务。更好的方法是让您的Web请求在数据库中存储请求信息,并在后端获得一些Windows服务并进行处理。 UI可以简单地检查数据库以获取给定任务的更新。
答案 1 :(得分:1)
Marcin是对的。我赞成这个答案,但我想我应该解释一下。 TPL本身不会导致资源泄漏。如果您遇到任何资源泄漏,请阅读this article。 : - )
Marcin对于IIS回收AppPool并导致“数据丢失”的可能性也是正确的。我们有类似的情况,发现发生的次数比人们想象的要多。我们稍微重新设计了我们的服务以接收触发器消息,告知它“嘿,你有一些数据在数据库中等着你。”这消除了轮询的需要。执行的功能是一个多步骤过程,每个步骤都会更新数据库,这样如果服务在中途重新启动/回收,它就可以从停止的位置进行拾取。您不需要将其转换为Windows服务,但如果您想要或需要将其移动到其他非Web服务器,则可以。
如果您担心假脱机太多线程,请查看this SO Q&A。
教学说明:异步和即发即弃不一样。异步意味着“我想要一个答案,但不能等待,所以一旦你完成,请稍后再打电话给我。” “一劳永逸”的意思是“这里有一些数据/信息。做你用它做什么,但不要打电话给我。我不在乎,或者如果我想知道,我会稍后回电。”