在异步任务完成之前返回

本文关键字:返回 异步 任务 | 更新日期: 2023-09-27 18:01:24

我正在做一个ASP。NET MVC 4 web应用程序。我正在使用。net 4.5,并试图利用新的异步API的优势。

我有一些情况,我想安排一个异步任务稍后运行,而我立即返回一个重要的值。例如,这里是一个"登录"方法,我想尽快返回一个新的SessionID,但是一旦我返回了SessionID,我想清除旧的过期SessionID:

public async Task<Guid> LogIn(string UserName, string Password)
{
    //Asynchronously get ClientID from DB using UserName and Password
    Session NewSession = new Session()
    {
        ClientID = ClientID,
        TimeStamp = DateTime.Now
    };
    DB.Sessions.Add(NewSession);
    await DB.SaveChangesAsync();    //NewSession.ID is autopopulated by DB
    CleanSessions(ClientID);    //Async method which I want to execute later
    return NewSession.ID;
}
private async void CleanSessions(int ClientID)
{
    //Asynchronously get expired sessions from DB based on ClientID and mark them for removal
    await DB.SaveChangesAsync();
}

我尝试了一堆不同的东西,包括Task.Run()和Parallel.Invoke()的组合,但从未调用过清洗。如何实现后台任务调度?

在异步任务完成之前返回

在ASP中运行任务。不建议在没有请求的情况下使用NET。这是危险的。

也就是说,将CleanSessions更改为返回Task,您可以这样做:

Task.Run(() => CleanSessions());

在你的情况下,我认为这将是好的,因为没有长期的问题,如果CleanSessions不执行或在执行的中间终止(这可能发生在ASP。. NET(由于回收)。如果你想通知ASP。如果您正在进行一些与请求无关的工作,您可以使用我博客中的BackgroundTaskManager,如下所示:

BackgroundTaskManager.Run(() => CleanSessions());

如果,正如已经注意到的那样,您正在尝试做一些"着火后忘记"的事情,但是在ASP中。NET -然后你可能想看看ConfigureAwait;您可以使用它作为await的一部分,告诉它忽略同步上下文。同步上下文将它与ASP联系起来。. NET执行管道,但如果没有必要,可以避免使用它。例如:

public async Task<Guid> LogIn(string UserName, string Password)
{
    //Asynchronously get ClientID from DB using UserName and Password
    Session NewSession = new Session()
    {
        ClientID = ClientID,
        TimeStamp = DateTime.Now
    };
    DB.Sessions.Add(NewSession);
    await DB.SaveChangesAsync().ConfigureAwait(false);    //NewSession.ID is autopopulated by DB
    await CleanSessions(ClientID).ConfigureAwait(false);    //Async method which I want to execute later
    return NewSession.ID;
}
// simplified: no need for this to be full "async"
private Task CleanSessions(int ClientID)
{
    //Asynchronously get expired sessions from DB based on ClientID
    return DB.SaveChangesAsync();
}