我正在寻找关于火灾的最佳做法的信息并忘记asp.net mvc行动...基本上我想要一个移动客户端来打电话;服务器启动异步任务;然后尽快返回移动客户端。
但我想确保,假设没有异常,异步任务将成功完成。显然有几种不同的选择:
我认为任务在这里是最好的选择,但是想从SO获得想法。
编辑:根据已有的一些答案澄清:客户端不需要回复。我希望一旦服务器开始异步任务,HTTP请求就会尽快完成。我知道客户端上的异步模式,但是我想限制移动设备维持连接打开所需的时间。此外,希望避免有一个单独的进程轮询或推送消息(通过队列,总线等),因为这是过度杀伤。我只想在数据库中记录某些东西,在IO完成之前,客户端不需要保持连接。
答案 0 :(得分:18)
我知道这是一个老问题,但这是我对这些事情的看法,因为我不同意接受的答案。
您不需要AsyncController
,因为您对等待异步操作无法完成感兴趣。因此,关于MVC方面的问题的答案是:无所谓。你可以用任何方式完成你的工作,并且只需要一个常规的旧动作来启动过程并返回你想要的任何结果。
你问题的第二部分确实更相关。您希望确保您的异步任务不会发生任何事情,因为您已经从Web进程启动它们,假设任务本身不会抛出异常。答案取决于您的可靠性要求。
您提到您不需要单独的流程,这限制了您的选择。您的任务将与您的Web应用程序在同一个应用程序域中运行。如果有任何事情导致应用程序域或进程失效,您的任务将会死亡,可能处于一种奇怪的状态。这甚至不一定来自未处理的例外情况。可以将IIS设置为不时或在某些条件下自动回收应用程序。或者,如果您发布新代码或触摸bin目录中的任何内容,您的应用程序域将在所有请求完成后拆除,并启动新的请求。如果这些案例对你来说是个噱头,那么你别无选择,只能将你的任务移出进程并与某种消息进行沟通。
如果你不担心IIS杀了你,你还是要担心自己。如果您没有最后机会使用AppDomain.UnhandledException
事件处理它们,那么来自其他后台任务的未处理异常将导致该过程失效。在使用任务并行库的情况下,如果您Wait
或查看Result
或Exception
属性而没有注意到的例外情况下的任务将导致此过程失效不要在TaskScheduler.UnobservedTaskException
事件中最后一次观察它们。
另外需要注意的是,用于后台操作的任何ThreadPool线程都无法在此期间为您的Web应用程序提供请求。您可以管理池中的最大线程,或者改为启动新线程。或者,如果您将TPL与默认调度程序一起使用,请使用LongRunning
提示安排任务以有效获取新线程。
答案 1 :(得分:11)
public async Task<ActionResult> Index()
{
// Start all operations.
var tasks = new[]
{
Task.Run(() =>TestOutput.DoWork("1")),
Task.Run(() =>TestOutput.DoWork("2")),
Task.Run(() =>TestOutput.DoWork("3"))
};
// Asynchronously wait for them all to complete.
// Uncomment below line to not forget the results
// var results = await Task.WhenAll(tasks);
// Return empty string for fire and forget.
return View(string.Empty);
}
答案 2 :(得分:1)
你是矛盾的
你的问题标题明确地说“火与忘记”然后在你的问题中你提到相反的
基本上我想要一个移动客户端来打电话;服务器启动异步任务; 然后尽快返回到移动客户端。
那么,你想要一个异步通话,它会发回一个结果,还是一个 Fire and forget 来电?
如果是正常的异步调用,只需在您喜欢的javascript库中使用相同的jQuery .ajax()
方法,并在success
属性函数中连接您的返回值。
如果发生火灾并忘记,最好的方法是让服务器在数据库的TBL_JOBS
表中插入一行,然后你可以有一个重复的脚本来选择这个并处理信息。
答案 3 :(得分:1)
我建议使用AsyncController
。您应该在http://bradwilson.typepad.com/presentations/advanced-mvc-3.zip