我该如何在ASP.net MVC中正确执行异步方法?

5
如何在控制器方法内执行异步方法并返回HttpStatusCodeResult(200),而不会使异步代理提前终止执行?
我正在开发一个asp.net应用程序,其中一个主页控制器的操作需要很长时间才能运行(10-30秒)。我想返回HttpStatusCodeResult(200)并继续运行我的函数。该函数不需要返回任何内容,但仍然不是“点燃并忘记”情况,因为我立即通过HttpStatusCodeResult向服务器返回响应。
我尝试使用委托,但是一旦从action中返回状态代码,委托就停止执行。另一个选项是创建Windows服务,但这就像使用重型武器解决小问题。我的请求非常少,因此在我的情况下,资源和性能都不是问题。我听说ThreadPool.QueueUserWorkItem是一种选择,但哪种最适合我的情况?

这可能是您最好的选择:在ASP.NET MVC中使用异步控制器 - Chris Gessler
但我认为它只是优化了线程池的使用,我的意思是我不能返回http状态码并继续执行,请查看“将同步操作方法转换为异步操作方法”部分。 - Yehia A.Salam
1个回答

1
创建一个静态类来管理这个长时间运行的操作。该类将负责创建线程来执行任务,并提供一种检查任何正在进行的操作状态的方法(即,如果它仍在进行或已完成,如果已完成,则是什么结果)。
然后,您的MVC控制器方法使用此类来完成工作并向用户呈现状态信息或已处理的数据。
类似于这样:
public ActionResult GetSomething(String id) {
    TaskResult result = TaskClass.GetStatus( id );
    if( result == null ) { // the task has not been run, so start it up
        TaskClass.StartNew( id );
        return new View("PleaseWait");
    } else if( !result.IsFinished ) {
        return new View("PleaseWait");
    } else {
        return View("Results", result);
    }
}

public static class TaskClass {
     private static Dictionary<String,TaskResult> _tasks;
     public static TaskResult GetStatus(String id) {
         // TODO: Make this code thread-safe
         if( _tasks.ContainsKey(id) ) return _tasks[id];
         return null;
     }
     public static void Start(String id) {
         _tasks.Add( id, new TaskResult("Working") );
         Thread thread = new Thread( SomeExpensiveOperation );
         thread.Start( id );
     }
}

在 SomeExpensiveOperation 结束时,会有一些代码将 TaskResult 标记为已完成。

这听起来很不错。我唯一没能完全想明白的部分是:当控制器方法执行完成后,还有谁在等待异步结果? - Robert Harvey
不需要任何人监听。只需将完成操作的结果存储在内存中,直到客户端请求它。请参见我的更新答案以获取示例。在这种情况下,我使用了一个字典(请注意,我的代码不是线程安全的,并且存在许多错误,但您应该能够获得一般想法)。 - Dai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接