ASP.NET Web Forms Long Term Management Strategy

We have some logic for calculating the costly user value for our ASP.NET Web Forms application. It is currently located in a user control Page_Loadthat is on every page, for example:

//note that we are not awaiting this
Task.Factory.StartNew(() => CacheManager.GetExpensiveValue(UserId));

And then in static CacheManager.GetExpensiveValue(int userID):

private static object locker = new object();

lock (locker)
{
    if (!AlreadyDone(userID))
    {
        var expensiveValue = ReallyExpensiveMethod(userID);
        //our static cache wrapper class that uses an ObjectCache object
        OurCache.Add(userID, expensiveValue);
    }
    else
    {
        return OurCache.Get(userID);
    }
}

This works, but when it ReallyExpensiveMethod()takes REALLY a long time (I am also working on improving logic performance), users will block this lockwhen navigating between pages.

, , ? ConcurrentDictionary , ReallyExpensiveMethod(), - UserID, , , .

, , , , , Async="true" , .

+4
1

, , ?... []

. ; , - SignalR ( , , ).

, lock; , .

, ( ) .

. ASP.NET, , .

. ConcurrentDictionary , .

, - :

// In Page_Load
CacheManager.GetOrAdd(UserID);

Task<Results> CacheManager.GetOrAdd(int userId)
{
  lock (locker)
  {
    if (!OurCache.Contains(userId))
    {
      var task = Task.Run(() => ReallyExpensiveMethod(userId));
      OurCache.Add(userId, task);
      return task;
    }
    else
      return OurCache.Get(userId);
  }
}

// Usage:
Results results = CacheManager.GetOrAdd(UserID).Result;

( Task<T>.Result ), , .

. , , , .

+6

Source: https://habr.com/ru/post/1538863/


All Articles