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

c#在父级返回时在后台运行异步任务,c#,asp.net-mvc,asynchronous,C#,Asp.net Mvc,Asynchronous,我正在编写一个MVC5应用程序,它有一个带有函数的控制器,比如说Method1 我有一个第三方函数,它是async Task,我们称它为DoMethodAsync(它本质上是进行后期调用) 我想在从Method1返回之前调用它,但我并不真正关心异步任务的结果,如果它失败,它就会失败。我怎样才能触发并忘记它,并让它在后台执行,这样它就不会阻止控制器响应其他请求 如何确保DoMethodAsync仅在Method1返回后执行 调用异步方法意味着调用方法(您的代码)在异步方法执行时不会被阻止,至少在默

我正在编写一个MVC5应用程序,它有一个带有函数的控制器,比如说
Method1

我有一个第三方函数,它是
async Task
,我们称它为
DoMethodAsync
(它本质上是进行后期调用)

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


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

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

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
}
我并不真正关心异步任务的结果,如果它失败了,它也会失败

真的吗?只是问一下,因为这是一个极其罕见的用例

我怎样才能触发并忘记它,并让它在后台执行,这样它就不会阻止控制器响应其他请求

我有一个研究ASP.NET上“触发并忘记”任务的各种方法的网站

您不希望只调用该方法而忽略返回的任务,因为该方法将继承发起请求的请求上下文。然后,在请求完成后,处理请求上下文,该方法可以在一个“有趣”的地方结束-有些事情可以工作,但有些事情不行

因此,最低可行的解决方案是将其包装在
任务中。运行

var _ignored = Task.Run(() => DoMethodAsync());
但是,请注意,ASP.NET完全不知道这个“额外操作”。如果希望
DoMethodAsync
有更多的机会实际执行到完成,则需要使用
HostingEnvironment.QueueBackgroundWorkItem
(4.5.2+)或(4.5.0/4.5.1)向ASP.NET运行时注册它


还要注意的是,这些选项都不能保证
DoMethodAsync
将运行到完成;他们只是给了你一个“最大的努力”。对于一个真正可靠的系统,你需要一个合适的分布式体系结构,也就是说,一个独立处理器的可靠存储。

我知道这很旧,但在我自己搜索和尝试了几个小时后,我发现了这个线程。结合这里的一些信息和其他资源,我能够实现我想要的,我相信这和OP想要的是一样的

我想调用像/API/Start这样的URL,我想让该URL立即返回一个视图,上面写着“感谢您的启动,稍后再查看”。然而,它需要的只是开始一项背景工作

这是与MVC5,所以不确定它是否有区别,但

旁注:要查看此操作,请使用2个URL
/默认/索引那么您是想在Method1返回之前还是之后调用异步函数?这是一个asnyc函数。。。因此,无论你把它叫到哪里,只要你不等待它,它就不会阻塞控制器。只要不等待
DoMethodAsync
,这将生成一个编译器警告,但你可以忽略它,因为它正在做你想做的事。@codinggorilla哦哇,真的吗?我能做到吗@JonathanCarroll我希望返回后运行
DoMethodAsync
。但是由于
Method1
是控制器可以访问的唯一功能,因此我必须在其内部创建
DoMethodAsync
,然后再返回酷!但是如果我想保证
DoMethodAsync
Method1
返回后执行该怎么办?但是我无法访问
方法1
之外的内容。有没有更好的方法在
DoMethodAsync
上设置时间?@zaftcoAgeiha您想要做的事情的目的是什么?只要是非阻塞异步任务,它会有什么区别谢谢您详细的回答。首先,我很在乎,但我宁愿先让它工作起来。如果它改变了实现,那么我肯定会选择一个可以让我抓住失败的方法。使用
Run
它不会阻止调用方吗?你说的“不保证完成”是什么意思?他们会中途停止还是不执行?我考虑过吊火,但喜欢比较轻的。first@zaftcoAgeiha:我的意思是ASP.NET是围绕响应请求而设计的。它不是用来做请求之外的工作的。当没有请求时,IIS可以将其关闭(并偶尔将其回收以保持干净)。如果你有一个
任务。在那个时候运行
任务,它会被随意杀死。@Stephen Cleary我去了may教程。。只有这个答案可以帮助。。现在,我的代码正在运行,不会影响用户的工作体验。非常感谢。您希望根据请求启动后台工作并不是“非常罕见的用例”,但您不希望请求等待工作完成。你认为忘记密码机制是一个极其罕见的用例吗?你认为记录用户活动却不想让他们的请求陷入等待记录操作完成的困境是极其罕见的吗?@CarlLeth:我说过,很少不关心操作是否失败(或者是否完成)。忘记密码机制忽略所有电子邮件发送错误是极为罕见的。忘记密码的常见解决方案是适当的分布式体系结构(队列+服务);日志记录的常见解决方案是在关闭时刷新内存队列。异步的fire和forget应该非常简单
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()}");
    }      

}