Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步任务完成前返回_C#_Asp.net Mvc 4_.net 4.5_Async Await - Fatal编程技术网

C# 异步任务完成前返回

C# 异步任务完成前返回,c#,asp.net-mvc-4,.net-4.5,async-await,C#,Asp.net Mvc 4,.net 4.5,Async Await,我正在开发一个ASP.NETMVC4Web应用程序。我正在使用.NET4.5,并试图利用新的异步API 我有两种情况需要安排一个异步任务稍后运行,同时立即返回一个立即重要的值。例如,这里有一个“Login”方法,我想尽快返回一个新的SessionID,但一旦返回SessionID,我想清除旧的过期SessionID: public async Task<Guid> LogIn(string UserName, string Password) { //Asynchronous

我正在开发一个ASP.NETMVC4Web应用程序。我正在使用.NET4.5,并试图利用新的异步API

我有两种情况需要安排一个异步任务稍后运行,同时立即返回一个立即重要的值。例如,这里有一个“Login”方法,我想尽快返回一个新的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();
}
公共异步任务登录(字符串用户名、字符串密码)
{
//使用用户名和密码从DB异步获取ClientID
会话NewSession=新会话()
{
ClientID=ClientID,
TimeStamp=DateTime.Now
};
DB.Sessions.Add(NewSession);
wait DB.SaveChangesAsync();//NewSession.ID由DB自动填充
CleanSessions(ClientID);//我想稍后执行的异步方法
返回NewSession.ID;
}
私有异步void清理(int-ClientID)
{
//基于ClientID从DB异步获取过期会话,并将其标记为删除
等待DB.saveChangesSync();
}

我尝试了很多不同的方法,包括Task.Run()和Parallel.Invoke()的组合,但从未调用过CleanSessions。如何实现后台任务调度?

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

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

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

在您的情况下,我认为这是可以的,因为如果<代码> CudioStudio在执行过程中不执行或终止(如果由于回收而在ASP.NET中发生),则不会有长期问题。如果要通知ASP.NET您有一些与请求不相关的正在进行的工作,可以使用以下命令:

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

如前所述,如果您试图在ASP.NET中执行“触发并忘记”操作,那么您可能需要查看
ConfigureAwait
;您可以将其作为
wait
的一部分来告诉它忽略同步上下文。正是同步上下文将其绑定回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();
}
公共异步任务登录(字符串用户名、字符串密码)
{
//使用用户名和密码从DB异步获取ClientID
会话NewSession=新会话()
{
ClientID=ClientID,
TimeStamp=DateTime.Now
};
DB.Sessions.Add(NewSession);
await DB.SaveChangesAsync().ConfigureAwait(false);//NewSession.ID由DB自动填充
await CleanSessions(ClientID).ConfigureAwait(false);//我想稍后执行的异步方法
返回NewSession.ID;
}
//简化:不需要完全“异步”
私有任务清理(int ClientID)
{
//基于ClientID从数据库异步获取过期会话
返回DB.saveChangesSync();
}

基于此,
CleanSessions
应该在
savechangesync
完成时开始。它也许可以通过
任务
等待
来捕获错误等-但从我看到的情况来看,它应该“按原样”工作。注意:您永远不应该使用
异步无效
作为您的方法,除了顶级事件处理程序之外。@marcGravel:ASP.NET将在发送响应之前等待所有
async void
方法的完成。op想要一把火,忘掉它。@StephenCleary啊,我错过了ASP.NET该死的同步上下文。这个解决方案有最好的错误处理能力(在
CleanSessions
上使用
Wait
),但不会“早”返回响应;响应将在
CleanSessions
完成后发送。啊,是的-尽管此代码使用了ConfigureAwait,但在这些“等待”完成之前,显然无法发送响应。因此,如果您想象调用代码等待此任务,它将在ASP.NET同步上下文中。是的,我尝试了一下,它仍然在等待CleanSessions()之后才能继续。这并没有完成我想要做的。这正是我想要的,谢谢。实际上我已经试过了,但是我的CleanSessions()方法中有一个bug导致了一个异常,并且因为该方法在没有请求的情况下执行,所以没有捕获到异常。这给我的印象是该方法根本没有被调用!因此,请注意任何想使用这个技巧的人,一定要阅读这个答案中的链接,并确保你真正理解为什么这是“危险的”。4年后怎么样?也许是最新消息?你的博客自2014年以来一直没有更新过,有什么新的见解吗?@CularBytes:No;ASP.NET仍然以同样的方式工作,这个答案仍然是完全正确的
BackgroundTaskManager
无法在ASP.NET Core上工作,但您可以使用
IHostedService
或使用
IApplicationLifetime
而不是
iRegistereObject
来完成同样的工作。感谢您的更新。最终只是将其移动到WebJobs,调用API端点并在稍后(计划)完成工作