1

I find several answers bashing use of session state in async fashion, eg.

Are there some conditions under which updating session from async thread will not or can not work?

My use case is as follows:

In app, user profile data is stored in session. Aim to asynchronously refresh the profile data when an admin changes a user's name, groups, or other profile info, etc.

Async thrust: poll a database table that stores the user id's whose data has changed. if data matches current user id, refresh profile data, remove id from table

I find the following code updates a session key asynchronously.

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
    }


}

Are there any additional considerations or protections - besides a null check - that I should take when writing to session data from the async task?

Community
  • 1
  • 1
monkeyhouse
  • 2,875
  • 3
  • 27
  • 42

1 Answers1

2

Using Task.Factory.StartNew in ASP.NET is dangerous and may lead to unexpected behavior

The reason is that the ASP.NET runtime has no idea that you’ve queued this work, so it’s not aware that the background work even exists. For a variety of reasons, IIS/ASP.NET has to occasionally recycle your application. If you have background work running when this recycling takes place, that work will mysteriously disappear

Moreover, HttpContext.Current.Session is not thread-safe. When consuming multiple requests asynchronously on the same key you may run into race conditions leading to invalid data.

I would strongly advise you to look at alternatives:

  1. Use a persistent queue (as Stephan suggests in his blogpost) such as MSMQ or Azure MB.

  2. Use either HostingEnvironment.QueueBackgroundWorkItem or alternativley Stephans BackgroundTaskManager which register work with the ASP.NET ThreadPool.

  3. Consider running this code synchronously

You should also read more about Returning Early From ASP.NET Requests and Using Task.Run in a syncronous asp.net controller

Community
  • 1
  • 1
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321