c#在父级返回时在后台运行异步任务

时间:2016-03-01 19:25:59

标签: c# asp.net-mvc asynchronous

我正在编写一个MVC5应用程序,其控制器的函数为Method1

我有一个async Task的第三方功能,让我们称之为DoMethodAsync(它本质上是一个POST呼叫)。

我想在从Method1返回之前调用它,但我并不真正关心异步任务的结果,如果失败,则失败。如何触发并忘记并让它在后台执行,以便它不会阻止控制器响应其他请求?

如何确保DoMethodAsync仅在Method1返回后执行?

4 个答案:

答案 0 :(得分:10)

  

我真的不关心异步任务的结果,如果失败,它就会失败。

真的?只是问,因为这是一个非常罕见的用例。

  

如何触发并忘记并让它在后台执行,以便它不会阻止控制器响应其他请求?

我有一个blog post,可以查看各种方法来解雇和忘记" ASP.NET上的任务。

想要只调用该方法并忽略返回的任务,因为该方法将继承启动请求的请求上下文。然后在请求完成之后,处理请求上下文,并且该方法可以最终在有趣的"地方 - 有些东西会起作用,但有些东西不会。

因此,最小可行解决方案是将其包装在Task.Run

var _ignored = Task.Run(() => DoMethodAsync());

但请注意,ASP.NET完全没有意识到这个"额外的操作"。如果您希望DoMethodAsync有更多机会实际执行完成,那么您将要使用HostingEnvironment.QueueBackgroundWorkItem(4.5.2+)向ASP.NET运行时注册它或my own BackgroundTaskManager.Run(4.5.0 / 4.5.1)。

另请注意,这些选项的 none 将保证DoMethodAsync将完成运行;他们只是给你最好的努力。"对于真正可靠的系统,您需要一个适当的分布式架构,即具有独立处理器的可靠存储。

答案 1 :(得分:1)

我知道这很古老,但是经过数小时的搜索和尝试其他事情,我遇到了这个问题。将此处的一些信息与其他资源结合起来,我能够实现我想要的东西,我认为这与OP想要的东西一样。

我想调用/ API / Start之类的URL,并且希望该URL立即返回一个视图,该视图显示“感谢您启动,请稍后再回来查看”。但是,它只需要简单地启动后台工作即可。

这是与MVC 5一起使用的,因此不确定是否会有所作为,但是...

侧面注:要查看实际效果,请使用2个网址 /默认/索引<-将报告约5秒 / Default / IndexAsync <-会报告约0秒(有点..您会看到)

public class DefaultController : Controller
{

    // GET: Sync
    public ActionResult Index()
    {
        System.Diagnostics.Stopwatch myStopwatch = new System.Diagnostics.Stopwatch();
        myStopwatch.Start();
        DoTask();
        myStopwatch.Stop();

        ViewBag.Message = ($"Process took {myStopwatch.Elapsed.TotalSeconds.ToString()}");
        return View("Index");
    }

    // GET: Async
    public ActionResult IndexAsync()
    {
        System.Diagnostics.Stopwatch myStopwatch = new System.Diagnostics.Stopwatch();
        myStopwatch.Start();
        Task.Factory.StartNew(DoTaskAsync);
        myStopwatch.Stop();

        ViewBag.Message = ($"Process took {myStopwatch.Elapsed.TotalSeconds.ToString()}");
        return View("Index");
    }

    // "the Sync Task"
    private void DoTask()
    {
        System.Diagnostics.Debug.Print($"DoTask Started at {DateTime.Now.ToString()}");
        System.Threading.Thread.Sleep(5000);
        System.Diagnostics.Debug.Print($"DoTask Finished at {DateTime.Now.ToString()}");
    }

    // "the Async Task"
    private async Task DoTaskAsync()
    {
        System.Diagnostics.Debug.Print($"DoTaskAsync Started at {DateTime.Now.ToString()}");
        System.Threading.Thread.Sleep(5000);
        System.Diagnostics.Debug.Print($"DoTaskAsync Finished at {DateTime.Now.ToString()}");
    }      

}

答案 2 :(得分:0)

调用异步方法意味着在异步方法执行时,将阻止调用方法(您的代码),至少在默认情况下不会被阻止(您可以通过&#进行代码阻止) 39;等待关键字或通过调用任务的阻止方法之一,例如&#39;结果&#39;或等等...等。)。
这意味着如果您只是调用该方法,该方法将异步运行,您的代码将不会等待它结束。我认为这正是你想要的。

答案 3 :(得分:0)

public ActionResult Index()
{
    DoMethodAsync(); // if you do not await and simple call this task it will run in backround as you want
    return View();
}

async Task DoMethodAsync()
{
    // calculate something
}