Mar*_*rco 14 c# asp.net-mvc asynchronous async-await asp.net-mvc-3
我有以下mvc动作.
public async Task<JsonResult> DoSomeLongRunningOperation()
{
return await Task.Run(() =>
{
//Do a lot of long running stuff
//The underlying framework uses the HttpContext.Current.User.Identity.Name so the user is passed on the messagebus.
}
}
Run Code Online (Sandbox Code Playgroud)
在任务中,HttpContext变为null.我们做了很多尝试,但没有任何事情让我们确信HttpContext总是在我们的新线程中可用.
有没有在异步任务中使用HttpContext的解决方案?
在我们的IocContainer中,我们注册了以下对象,该对象将用户名传递给框架.
public class HttpContextUserIdentityName : ICredentials
{
public string Name
{
get { return HttpContext.Current.User.Identity.Name; }
}
}
Run Code Online (Sandbox Code Playgroud)
在持久化到数据库之前,在很多地方调用此代码.
我们需要另一种方法来获取用户的用户名启动webrequest或修复HttpContext为null的问题.
因为持久化到数据库发生在任务中,所以在进入任务之前无法访问HttpContext.
我也想不出一个临时持久保存用户名的安全方法,所以我可以实现另一个ICredentials服务对象.
您几乎不想Task.Run在ASP.NET方法中使用.
我认为最干净的解决方案(但最多的工作)是async在其他层实现兼容的接口:
public async Task<JsonResult> DoSomeLongRunningOperation()
{
//Do a lot of long running stuff
var intermediateResult = await DoLongRunningStuff();
return await DetermineFinalResult(intermediateResult);
}
Run Code Online (Sandbox Code Playgroud)
在启动新线程之前,您应该从当前上下文中获取所需的任何信息。在这种情况下,添加如下内容:
string username = HttpContext.Current.User.Username;
Run Code Online (Sandbox Code Playgroud)
然后Task.Run在另一个线程内部使用它。
顺便说一句,就目前情况而言,这项任务没有理由await。您可以直接返回任务,而不将方法标记为Async。
如果您需要访问该Response对象,这可能会利用长时间运行操作的结果,因此不能在您应该在之后Task.Run执行此操作(但确保任务已完成)。如果您最终这样做,那么您就无法执行我在上一段中建议的操作。Task.Runawait
| 归档时间: |
|
| 查看次数: |
14029 次 |
| 最近记录: |