在asp.net-mvc中,如何在不降低用户体验的情况下运行昂贵的操作?我有一个asp.net-mvc网站,我正在为我的ORM使用nhibernate。我有一个当前控制器操作,它执行基本的CRUD更新(从数据库中查询项目,然后更新一堆值并提交回db表)。然后它向客户端返回一个简单的JSON响应以指示成功或错误。publicActionResultUpdateEntity(MyEntitynewEntity){varexistingEntity=GetFromRepository(newEntity.Id);更新现有实体(新实体,现有实体);返回Json(SuccessMessage);在某些情况下(假设提交成功并且我的一些对象字段发生了变化)我现在想触发一些额外的操作(比如给一群人发电子邮件并运行一些生成报告的代码)但我不想放慢并降低进行更新的人员的用户体验。所以我担心的是如果我这样做:publicActionResultUpdateEntity(MyEntitynewEntity){boolkeyFieldsHaveChanged=UpdateExistingEntity(newEntity,existingEntity);如果(keyFieldsHaveChanged){GenerateEmailGenerates(););}返回Json(SuccessMessage);这对于某人更新的用户体验来说太慢了。无论如何(asyncc?)有一个由控制器动作触发的昂贵操作,但没有控制器动作因此而减慢?我以前做过这个。最强大的方法是使用异步控制器,或者更好的是使用独立服务,例如WCF服务。但根据我的经验,我只需要执行“简单”的单行任务,例如您所说的审计或报告。在那个例子中,简单的方法-启动任务:publicActionResultDo(){SomethingImportantThatNeedsToBeSynchronous();Task.Factory.StartNew(()=>{AuditThatTheUserShouldntCareOrWaitFor();SomeOtherOperationTheUserDoesntCareAbout();});返回视图();这是一个简单的例子。您可以根据需要启动任意数量的任务、同步它们、在完成时收到通知等。我目前正在使用上述方法进行AmazonS3上传。如果你打算立即返回JSON,让密集的工作在后台异步运行而不影响用户体验,那么你需要启动一个新的后台线程。AsyncController不会在这里帮助你。有很多关于通过这样做使线程请求池挨饿的争论(这是真的),但相反的争论是你应该让池挨饿,因为服务器正忙于工作。理想情况下,您应该通过排队/分布式系统等将工作完全转移到另一台服务器,但这是一个复杂的解决方案。除非你需要处理数百个请求,否则你不需要考虑这个选项,因为它不太可能导致问题。这实际上取决于解决方案的可扩展性要求、后台进程需要多长时间以及它被调用的频率。最简单的解决方案如下:publicActionResultUpdateEntity(MyEntitynewEntity){varexistingEntity=GetFromRepository(newEntity.Id);boolkeyFieldsHaveChanged=UpdateExistingEntity(newEntity,existingEntity);如果(keyFieldsHaveChanged){ThreadPool.QueueoUser>Ite);生成报告();});}返回Json(SuccessMessage);您应该实施异步操作和异步控制器,以不锁定线程池并且不影响网站的其他用户。当一个任务长时间运行时,从asp.net线程池中获取的线程会被搁置,直到操作完成才会返回到池中。如果同时有许多长时间运行的任务,那么它们将保持多线程状态,因此访问您站点的其他用户可能会等待。ASYNC的操作不会使任何代码更快。我建议您仅针对我上面写的线程案例使用异步控制器,但这还不够。我认为您应该使用一些链接或ajax来触发服务器上的操作,以保持用户在网站上冲浪。操作完成后,在下一次页面刷新时,应通知用户任务已完成执行。这又一次证明业务代码不应该写在控制器中。您应该为此分离服务。这是一个老问题,所以我认为它需要更新。我推荐使用HangFire(http://hangfire.io)。有了这个,您甚至可以在Web应用程序中简单地排队您的作业。HangFire将确保作业至少运行一次。//静态方法用于演示目的BackgroundJob.Enqueue(()=>Console.WriteLine("Simple!"));您还可以在漂亮的UI中查看所有排队作业的状态。我认为您真的想要类似于WindowsAzure的辅助角色。http://www.microsoft.com/windowsazure/features/compute/我不确定如何在没有Azure排队的情况下在纯MVC中最好地实现它。而且,根据您托管的位置(互联网主机、您自己的根服务器等),会出现复杂情况。从@IKEARiot的Windows服务和数据库标志中汲取灵感,您可以使用Quartz.Net或Castle.Scheduler组件,它们可以集成到您的网站中,或者开发为能够运行特定作业的独立Windows服务。Stackoverflow-quartz-netvsasp-net当我正确阅读你的问题时,这主要不是异步的。这是一个长时间运行的操作。您应该将长时间运行的操作卸载到后台作业中。ASP.NET应用程序不太适合执行后台作业。我可以看到几个可供选择的选项:Windows服务-这可以轮询您的数据库的某个状态,并可以从该状态执行操作WCF服务-您的ASP.NET应用程序可以提供WCF服务可能还有其他类似的BizTalk用于发送异步请求而不等待响应,但这取决于您的应用程序结构等。在UI中,您应该能够轮询计时器以向用户提供状态(如果您认为用户需要知道该状态立即),或在操作完成后向用户发送电子邮件。另一方面,使用异步操作执行I/O非常重要,其他人已经提供了一些关于如何执行此操作的很好的链接。如果您考虑用户体验(用户不应该等待执行这些任务)和可靠性(即使应用程序重新启动,任务也必须排队和执行),您可以选择使用MSMQ。MSMQ为同步操作提供了最佳解决方案。它支持同步操作,提供日志记录和托管API,并且主要关注这种情况。查看这些文章:MSMQ编程简介.Net中的MSMQ使用服务总线在更新实体时发布消息。这样,您不仅可以避免在控制器中进行冗长的操作,还可以将控制器与发生某些事情时需要完成的操作分离。您还可以使用域事件来处理操作并将其与您最喜欢的IoC容器结合起来:AdvancedStructureMap:Wiringimplementationstoopengenerictypes以上是C#学习教程:在asp.net-mvc中,如何在没有用户体验的情况下运行昂贵的操作?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
