我发现有几个答案以异步方式抨击会话状态的使用,例如。
是否存在一些条件,在这些条件下,异步线程的更新会话不会或不能正常工作?
我的用例如下:
在应用中,用户个人资料数据存储在会话中。目标是在管理员更改用户的姓名,组或其他个人资料信息等时异步刷新配置文件数据。
异步推力: 轮询一个数据库表,该表存储其数据已更改的用户标识。 如果数据与当前用户ID匹配,请刷新配置文件数据,从表中删除id
我发现以下代码异步更新会话密钥。
public class MyAsyncUpdateController : Controller
{
public static string MyKey = "myKey";
public ActionResult Index()
{
Session[MyKey] = "Init Data: Updated at " + DateTime.Now.TimeOfDay;
Task.Factory.StartNew(session =>
{
Thread.Sleep(10000);
var _session = (HttpSessionState)session;
if (_session != null)
_session[MyKey] = "Async Data: Updated at " + DateTime.Now.TimeOfDay ;
}, System.Web.HttpContext.Current.Session);
return RedirectToAction("OtherAction");
}
public ActionResult OtherAction()
{
string result = "";
if (Session != null && Session[MyKey] != null)
result= Session[MyKey].ToString();
return Content(result);
//Refresh until see updated timestamp
}
}
在从异步任务写入会话数据时,我是否应该采取额外的考虑或保护 - 除了空检查之外?
答案 0 :(得分:2)
Using Task.Factory.StartNew
in ASP.NET is dangerous and may lead to unexpected behavior
原因是ASP.NET运行时不知道你已将这项工作排队,因此它不知道后台工作是否存在。出于各种原因,IIS / ASP.NET必须偶尔回收您的应用程序。如果你在进行这种回收时运行了后台工作,那么这项工作将会神秘地消失
此外,HttpContext.Current.Session
不是线程安全的。当在同一个密钥上异步使用多个请求时,您可能会遇到导致无效数据的竞争条件。
我强烈建议你看看替代方案:
使用持久性队列(如Stephan在其博文中所建议的那样),例如MSMQ或Azure MB。
使用注册使用ASP.NET ThreadPool的HostingEnvironment.QueueBackgroundWorkItem
或alternativley Stephans BackgroundTaskManager
。
考虑同步运行此代码
您还应该详细了解Returning Early From ASP.NET Requests和 Using Task.Run in a syncronous asp.net controller