10

我正在开发一个 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() 的组合,但 CleanSessions 永远不会被调用。如何实现后台任务调度?

4

2 回答 2

18

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

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

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

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

BackgroundTaskManager.Run(() => CleanSessions());
于 2013-02-27T23:39:02.860 回答
0

如果,如前所述,您正试图在 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();
}
于 2013-02-28T07:04:34.960 回答