异步更新会话数据

时间:2014-08-24 22:28:57

标签: c# session asynchronous task-parallel-library

我发现有几个答案以异步方式抨击会话状态的使用,例如。

是否存在一些条件,在这些条件下,异步线程的更新会话不会或不能正常工作?

我的用例如下:

在应用中,用户个人资料数据存储在会话中。目标是在管理员更改用户的姓名,组或其他个人资料信息等时异步刷新配置文件数据。

异步推力: 轮询一个数据库表,该表存储其数据已更改的用户标识。 如果数据与当前用户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
    }


}

在从异步任务写入会话数据时,我是否应该采取额外的考虑或保护 - 除了空检查之外?

1 个答案:

答案 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不是线程安全的。当在同一个密钥上异步使用多个请求时,您可能会遇到导致无效数据的竞争条件。

我强烈建议你看看替代方案:

  1. 使用持久性队列(如Stephan在其博文中所建议的那样),例如MSMQ或Azure MB。

  2. 使用注册使用ASP.NET ThreadPool的HostingEnvironment.QueueBackgroundWorkItem或alternativley Stephans BackgroundTaskManager

  3. 考虑同步运行此代码

  4. 您还应该详细了解Returning Early From ASP.NET Requests Using Task.Run in a syncronous asp.net controller