I have a singleton provider, where the main function is to retrieve an object from a webservice, and cache depending on the webservice cache headers response. This object will be accessed quite a lot. My question is when the data in the webservice changes, will any subsequent call to the singleton automatically be reflected?
public class ConfigurationProvider
{
#region Private Member Variables
private static readonly Lazy<ConfigurationProvider> _instance = new Lazy<ConfigurationProvider>(() => new ConfigurationProvider());
private static readonly HttpCache _cache = new HttpCache();
#endregion
#region Constructors
private ConfigurationProvider()
{
}
#endregion
#region Public Properties
public static ConfigurationProvider Instance
{
get { return _instance.Value; }
}
public ShowJsonResponse Configuration
{
get
{
// Try and get the configurations from webservice and add to cache
var cacheExpiry = 0;
return _cache.GetAndSet(WebApiConstant.ProxyCacheKeys.ShowJsonKey, ref cacheExpiry, () => GetConfiguration(ref cacheExpiry));
}
}
#endregion
#region Private Methods
private ShowJsonResponse GetConfiguration(ref int cacheExpiry)
{
var httpClient = new HttpClient();
try
{
var response = httpClient.GetAsync(WebApiConstant.Configuration.WebserviceUrl).Result;
if (response.IsSuccessStatusCode)
{
var showResponse = response.Content.ReadAsAsync<ShowJsonResponse>().Result;
if (response.Headers.CacheControl.Public && response.Headers.CacheControl.MaxAge.HasValue)
{
cacheExpiry = response.Headers.CacheControl.MaxAge.Value.Seconds;
}
// TODO: Remove when finished testing
// Default to 60 seconds for testing
cacheExpiry = 20;
return showResponse;
}
}
catch (HttpRequestException ex)
{
}
cacheExpiry = 0;
return null;
}
#endregion
}
The HttpCache class is just a wrapper around HttpRuntime Cache. The GetAndSet method just tries to retrieve the cache object and sets it if not found.
public override T GetAndSet<T>(string key, ref int duration, Func<T> method)
{
var data = _cache == null ? default(T) : (T) _cache[key];
if (data == null)
{
data = method();
if (duration > 0 && data != null)
{
lock (sync)
{
_cache.Insert(key, data, null, DateTime.Now.AddSeconds(duration), Cache.NoSlidingExpiration);
}
}
}
return data;
}
Usage example:
ConfigurationProvider.Instance.Configuration.Blah
Is there any perceived benefit to using the singleton pattern in this scenario, or instantiate the class regularly would be ok?
I think that the singleton pattern fits better in your case, and you won't need the object instance as well. Are you taking care of concurrency inside your HttpCache wrapper? It's important in order to avoid that concurrent threads could make multiple WS requests when two or more access the cache object at the same time or before the WS request returns.
I would suggest you to use the double lock/check pattern:
public override T GetAndSet<T>(string key, ref int duration, Func<T> method) {
var data = _cache == null ? default(T) : (T) _cache[key];
if (data == null) { //check
lock (sync) { //lock
//this avoids that a waiting thread reloads the configuration again
data = _cache == null ? default(T) : (T) _cache[key];
if (data == null) { //check again
data = method();
if (duration > 0 && data != null) {
_cache.Insert(key, data, null, DateTime.Now.AddSeconds(duration), Cache.NoSlidingExpiration);
}
}
}
}
return data;
}
Related
I am currently accessing my database directly when I get a GET-request by using something like this: _context.EXT_PRAMEX_INSERTS.Where(item => item.MatID == MaterialID.
But my database does not change very often so I want to create a data-class that fetches all tables on startup into lists.
And then I just parse the lists when I need to get any of the entries.
I was thinking that I could create a singleton-class that fetches all data on startup and then I just use that instance to get my data. But how do I access the context inside the singleton ? Or is there a better way to accomplish what I am trying to do ?
public sealed class ExternalDatabase
{
private static ExternalDatabase _instance = null;
private static readonly object _instanceLock = new object();
private List<EXT_PramexInserts>? pramexInserts;
private List<EXT_PrototypeEndmills>? prototypeEndmills;
private static List<IProducts> extAll = new List<IProducts>();
ExternalDatabase()
{
pramexInserts = pramexInserts == null ? _context.Set<EXT_PramexInserts>().ToList() : pramexInserts;
prototypeEndmills = prototypeEndmills == null ? _context.Set<EXT_PrototypeEndmills>().ToList() : prototypeEndmills;
if (extAll.Count == 0)
{
extAll = extAll.Union(pramexInserts).ToList().Union(prototypeEndmills).ToList();
}
}
public static ExternalDatabase Instance
{
get
{
lock (_instanceLock)
{
if (_instance == null)
{
_instance = new ExternalDatabase();
}
return _instance;
}
}
}
public List<IProducts> GetExtraData(string materialid)
{
var result = extAll.FindAll(p => p.MaterialID == materialid);
return result;
}
}
[ApiController]
[Route("DB")]
public class EXT_TablesController : ControllerBase
{
private readonly Context _context;
private static ExternalDatabase data = ExternalDatabase.Instance;
public EXT_TablesController(Context context)
{
_context = context;
}
//...
[HttpPost]
public IEnumerable<IProducts> Post([FromBody] EXT_Request request)
{
string selectedTable = null;
var (MaterialID, Type, Brand) = request;
if (Type != null && Brand != null)
{
selectedTable = $"EXT_{Brand}_{Type}";
switch (selectedTable)
{
case "EXT_PRAMEX_INSERTS":
//var items = _context.EXT_PRAMEX_INSERTS.Where(item => item.MatID == MaterialID);
return data.GetExtraData(MaterialID);
default:
return null;
}
}
return null;
}
}
It's better to keep your DbContext short-lived.
If you want to use the context in a singleton class, you can try DbContextFactory.
Also you may want to have a look at the secondary level cache pattern. Here is a ready-to-go package.
I don't know if it is the best answer but I followed one of the tips that Mehdi Dehghani suggested in the comment above.
I created a new context inside the singleton and it solved my problem.
I am using the code below to cache items. It's pretty basic.
The issue I have is that every time it caches an item, section of the code locks. So with roughly a million items arriving every hour or so, this is a problem.
I've tried creating a dictionary of static lock objects per cacheKey, so that locking is granular, but that in itself becomes an issue with managing expiration of them, etc...
Is there a better way to implement minimal locking?
private static readonly object cacheLock = new object();
public static T GetFromCache<T>(string cacheKey, Func<T> GetData) where T : class {
// Returns null if the string does not exist, prevents a race condition
// where the cache invalidates between the contains check and the retrieval.
T cachedData = MemoryCache.Default.Get(cacheKey) as T;
if (cachedData != null) {
return cachedData;
}
lock (cacheLock) {
// Check to see if anyone wrote to the cache while we where
// waiting our turn to write the new value.
cachedData = MemoryCache.Default.Get(cacheKey) as T;
if (cachedData != null) {
return cachedData;
}
// The value still did not exist so we now write it in to the cache.
cachedData = GetData();
MemoryCache.Default.Set(cacheKey, cachedData, new CacheItemPolicy(...));
return cachedData;
}
}
You may want to consider using ReaderWriterLockSlim, which you can obtain write lock only when needed.
Using cacheLock.EnterReadLock(); and cacheLock.EnterWriteLock(); should greatly improve the performance.
That link I gave even have an example of a cache, exactly what you need, I copy here:
public class SynchronizedCache
{
private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
private Dictionary<int, string> innerCache = new Dictionary<int, string>();
public int Count
{ get { return innerCache.Count; } }
public string Read(int key)
{
cacheLock.EnterReadLock();
try
{
return innerCache[key];
}
finally
{
cacheLock.ExitReadLock();
}
}
public void Add(int key, string value)
{
cacheLock.EnterWriteLock();
try
{
innerCache.Add(key, value);
}
finally
{
cacheLock.ExitWriteLock();
}
}
public bool AddWithTimeout(int key, string value, int timeout)
{
if (cacheLock.TryEnterWriteLock(timeout))
{
try
{
innerCache.Add(key, value);
}
finally
{
cacheLock.ExitWriteLock();
}
return true;
}
else
{
return false;
}
}
public AddOrUpdateStatus AddOrUpdate(int key, string value)
{
cacheLock.EnterUpgradeableReadLock();
try
{
string result = null;
if (innerCache.TryGetValue(key, out result))
{
if (result == value)
{
return AddOrUpdateStatus.Unchanged;
}
else
{
cacheLock.EnterWriteLock();
try
{
innerCache[key] = value;
}
finally
{
cacheLock.ExitWriteLock();
}
return AddOrUpdateStatus.Updated;
}
}
else
{
cacheLock.EnterWriteLock();
try
{
innerCache.Add(key, value);
}
finally
{
cacheLock.ExitWriteLock();
}
return AddOrUpdateStatus.Added;
}
}
finally
{
cacheLock.ExitUpgradeableReadLock();
}
}
public void Delete(int key)
{
cacheLock.EnterWriteLock();
try
{
innerCache.Remove(key);
}
finally
{
cacheLock.ExitWriteLock();
}
}
public enum AddOrUpdateStatus
{
Added,
Updated,
Unchanged
};
~SynchronizedCache()
{
if (cacheLock != null) cacheLock.Dispose();
}
}
I don't know how MemoryCache.Default is implemented, or whether or not you have control over it.
But in general, prefer using ConcurrentDictionary over Dictionary with lock in a multi threaded environment.
GetFromCache would just become
ConcurrentDictionary<string, T> cache = new ConcurrentDictionary<string, T>();
...
cache.GetOrAdd("someKey", (key) =>
{
var data = PullDataFromDatabase(key);
return data;
});
There are two more things to take care about.
Expiry
Instead of saving T as the value of the dictionary, you can define a type
struct CacheItem<T>
{
public T Item { get; set; }
public DateTime Expiry { get; set; }
}
And store the cache as a CacheItem with a defined expiry.
cache.GetOrAdd("someKey", (key) =>
{
var data = PullDataFromDatabase(key);
return new CacheItem<T>() { Item = data, Expiry = DateTime.UtcNow.Add(TimeSpan.FromHours(1)) };
});
Now you can implement expiration in an asynchronous thread.
Timer expirationTimer = new Timer(ExpireCache, null, 60000, 60000);
...
void ExpireCache(object state)
{
var needToExpire = cache.Where(c => DateTime.UtcNow >= c.Value.Expiry).Select(c => c.Key);
foreach (var key in needToExpire)
{
cache.TryRemove(key, out CacheItem<T> _);
}
}
Once a minute, you search for all cache entries that need to be expired, and remove them.
"Locking"
Using ConcurrentDictionary guarantees that simultaneous read/writes won't corrupt the dictionary or throw an exception.
But, you can still end up with a situation where two simultaneous reads cause you to fetch the data from the database twice.
One neat trick to solve this is to wrap the value of the dictionary with Lazy
ConcurrentDictionary<string, Lazy<CacheItem<T>>> cache = new ConcurrentDictionary<string, Lazy<CacheItem<T>>>();
...
var data = cache.GetOrData("someKey", key => new Lazy<CacheItem<T>>(() =>
{
var data = PullDataFromDatabase(key);
return new CacheItem<T>() { Item = data, Expiry = DateTime.UtcNow.Add(TimeSpan.FromHours(1)) };
})).Value;
Explanation
with GetOrAdd you might end up invoking the "get from database if not in cache" delegate multiple times in the case of simultaneous requests.
However, GetOrAdd will end up using only one of the values that the delegate returned, and by returning a Lazy, you guaranty that only one Lazy will get invoked.
I have a class that returns a cache, usage currently:
var cache = new ProductCache().Get();
then cache is a List<> that can be enumerated.
question is really should i populate this cache when ProductCache() is instantiated in the constructor, or when it is retrieved?
Option 1:
public class ProductCache
{
private readonly string key = "Product";
private readonly object cacheLock = new object();
ObjectCache cache = MemoryCache.Default;
public ProductCache()
{
}
public List<string> Get()
{
// Try to return.
var data = cache.Get(key) as List<string>;
if (data != null)
return data;
lock (cacheLock)
{
// Check again.
data = cache.Get(key) as List<string>;
if (data != null)
return data;
// Populate, and return.
data = PopulateFromElsewhere();
cache.Set(key, data, DateTimeOffset.UtcNow.AddSeconds(20));
return data;
}
}
private List<string> PopulateFromElsewhere()
{
return new List<string> { "Ball", "Stick" };
}
}
Option 2:
public class ProductCache
{
private readonly string key = "Product";
private readonly object cacheLock = new object();
ObjectCache cache = MemoryCache.Default;
public ProductCache()
{
var data = cache.Get(key);
if (data != null)
return;
lock (cacheLock)
{
// Check again.
data = cache.Get(key);
if (data != null)
return;
// Populate, and return.
PopulateFromElsewhere();
}
}
public List<string> Get()
{
return cache.Get(key) as List<string>;
}
private void PopulateFromElsewhere()
{
var data = new List<string> { "Ball", "Stick" };
cache.Set(key, data, DateTimeOffset.UtcNow.AddSeconds(20));
}
}
is the second option thread safe (enough)? i think the first one is....
there are other caches too.. and they are all similar, so i was planning on putting all the actual locking / loading behaviour in an abstract class
var storeCache = new StoreCache().Get();
var otherCache = new OtherCache().Get();
I guess the other option is a static class, but then there would need to be duplication of the locking mechanisms as i can't make that abstract... that could be quite nice, and used like...
var cache = GlobalCache.Stores();
If you want to reuse your cache logic but want flexibility in your child classes you could use Template method pattern:
public abstract class BaseCache
{
private readonly object cacheLock = new object();
protected ObjectCache cache = MemoryCache.Default;
public List<string> Get()
{
// for example. It could be anywhere and return any type.
ChildLogic();
var data = cache.Get(key);
if (data != null)
return;
lock (cacheLock)
{
// Check again.
data = cache.Get(key);
if (data != null)
return;
// Populate, and return.
PopulateFromElsewhere();
}
}
protected abstract void ChildLogic();
protected abstract void PopulateFromElsewhere();
}
And then in your child classes you should implement ChildLogic() and PopulateFromElsewhere() any way you want.
Of course you are not required to have method ChildLogic() at all.
I'd like to create a static Cached class for an ASP.NET MVC site for quick access to cached items like dropdown lists. It needs to have locking implemented so that when a key comes back empty it can be pulled from the repository while any other request threads wait on it to come back. As such, it needs per-method thread locking (versus a shared lock). My first thought was to use nameof as the lock for each method instead of creating a separate object to lock for each method. A simplified version would look something like...
public static class Cached
{
public static List<Country> GetCountriesList()
{
List<Country> cacheItem = null;
if (HttpContext.Current.Cache["CountriesList"] != null)
cacheItem = (List<Country>)HttpContext.Current.Cache["CountriesList"];
else
{
lock (nameof(GetCountriesList))
{
// Check once more in case it got stored while waiting on the lock
if (HttpContext.Current.Cache["CountriesList"] == null)
{
using (var repo = new Repository())
{
cacheItem = repo.SelectCountries();
HttpContext.Current.Cache.Insert("CountriesList", cacheItem, null, DateTime.Now.AddHours(2), TimeSpan.Zero);
}
}
else
cacheItem = (List<Country>)HttpContext.Current.Cache["CountriesList"];
}
}
return cacheItem;
}
public static List<State> GetStatesList()
{
List<State> cacheItem = null;
if (HttpContext.Current.Cache["StatesList"] != null)
cacheItem = (List<State>)HttpContext.Current.Cache["StatesList"];
else
{
lock (nameof(GetStatesList))
{
// Check once more in case it got stored while waiting on the lock
if (HttpContext.Current.Cache["StatesList"] == null)
{
using (var repo = new Repository())
{
cacheItem = repo.SelectStates();
HttpContext.Current.Cache.Insert("StatesList", cacheItem, null, DateTime.Now.AddHours(2), TimeSpan.Zero);
}
}
else
cacheItem = (List<State>)HttpContext.Current.Cache["StatesList"];
}
}
return cacheItem;
}
}
Is there anything glaringly wrong with an approach like this?
UPDATE:
Per the advice that it is a bad idea to lock on strings, I've changed it to a pattern that I found in SO's Opserver code that uses a ConcurrentDictionary to store a lock object per cache key. Is there anything wrong with the following:
public static class Cached
{
private static readonly ConcurrentDictionary<string, object> _cacheLocks = new ConcurrentDictionary<string, object>();
private const string KEY_COUNTRIES_LIST = "CountriesList";
public static List<Country> GetCountriesList()
{
List<Country> cacheItem = null;
var nullLoadLock = _cacheLocks.AddOrUpdate(KEY_COUNTRIES_LIST, k => new object(), (k, old) => old);
if (HttpContext.Current.Cache[KEY_COUNTRIES_LIST] != null)
cacheItem = (List<Country>)HttpContext.Current.Cache[KEY_COUNTRIES_LIST];
else
{
lock (nullLoadLock)
{
// Check once more in case it got stored while waiting on the lock
if (HttpContext.Current.Cache[KEY_COUNTRIES_LIST] == null)
{
using (var repo = new Repository())
{
cacheItem = repo.SelectCountries();
HttpContext.Current.Cache.Insert(KEY_COUNTRIES_LIST, cacheItem, null, DateTime.Now.AddHours(2), TimeSpan.Zero);
}
}
else
cacheItem = (List<Country>)HttpContext.Current.Cache[KEY_COUNTRIES_LIST];
}
}
return cacheItem;
}
private const string KEY_STATES_LIST = "StatesList";
public static List<State> GetStatesList()
{
List<State> cacheItem = null;
var nullLoadLock = _cacheLocks.AddOrUpdate(KEY_COUNTRIES_LIST, k => new object(), (k, old) => old);
if (HttpContext.Current.Cache[KEY_STATES_LIST] != null)
cacheItem = (List<State>)HttpContext.Current.Cache[KEY_STATES_LIST];
else
{
lock (nullLoadLock)
{
// Check once more in case it got stored while waiting on the lock
if (HttpContext.Current.Cache[KEY_STATES_LIST] == null)
{
using (var repo = new Repository())
{
cacheItem = repo.SelectStates();
HttpContext.Current.Cache.Insert(KEY_STATES_LIST, cacheItem, null, DateTime.Now.AddHours(2), TimeSpan.Zero);
}
}
else
cacheItem = (List<State>)HttpContext.Current.Cache[KEY_STATES_LIST];
}
}
return cacheItem;
}
}
Based on what you posted so far, I think you're over-thinking this. :) I don't see a need to populate yet another dictionary with your locking objects. Since you are using them in explicitly named methods, just declare them as fields as needed.
First, the advice to not lock on string values is sound, but based on the problem that two string values can appear identical while still being different objects. You could avoid that in your scenario by storing the appropriate string value in a const field:
public static class Cached
{
private const string _kcountries = "CountriesList";
private const string _kstates = "StatesList";
public static List<Country> GetCountriesList()
{
List<Country> cacheItem = (List<Country>)HttpContext.Current.Cache[_kcountries];
if (cacheItem == null)
{
lock (_kcountries)
{
// Check once more in case it got stored while waiting on the lock
cacheItem = (List<Country>)HttpContext.Current.Cache[_kcountries];
if (cacheItem == null)
{
using (var repo = new Repository())
{
cacheItem = repo.SelectCountries();
HttpContext.Current.Cache.Insert(_kcountries, cacheItem, null, DateTime.Now.AddHours(2), TimeSpan.Zero);
}
}
}
}
return cacheItem;
}
public static List<State> GetStatesList()
{
// Same as above, except using _kstates instead of _kcountries
}
}
Note that you shouldn't be using string literals throughout the code anyway. It's much better practice to define const fields to represent those values. So you kill two birds with one stone doing the above. :)
The only remaining problem is that you are still using a possibly-public value to lock, since the string literals are interned, and if the exact same string was used somewhere else, it would likely be the same interned value as well. This is of debatable concern; it's my preference to avoid doing so, to ensure no other code outside my control could take the same lock my code is trying to use, but there are those who feel such concerns are overblown. YMMV. :)
If you do care (as I do) about using the possibly-public value, then you can associate a unique object value instead of using the string reference:
public static class Cached
{
private const string _kcountriesKey = "CountriesList";
private const string _kstatesKey = "StatesList";
private static readonly object _kcountriesLock = new object();
private static readonly object _kstatesLock = new object();
public static List<Country> GetCountriesList()
{
List<Country> cacheItem = (List<Country>)HttpContext.Current.Cache[_kcountriesKey];
if (cacheItem == null)
{
lock (_kcountriesLock)
{
// Check once more in case it got stored while waiting on the lock
cacheItem = (List<Country>)HttpContext.Current.Cache[_kcountriesKey];
if (cacheItem == null)
{
using (var repo = new Repository())
{
cacheItem = repo.SelectCountries();
HttpContext.Current.Cache.Insert(_kcountriesKey, cacheItem, null, DateTime.Now.AddHours(2), TimeSpan.Zero);
}
}
}
}
return cacheItem;
}
// etc.
}
I.e. use the ...Key field for your cache (since it does require string values for keys) but the ...Lock field for locking (so that you are sure no code outside your control would have access to the object value used for the lock).
I'll note that you do have an opportunity to reduce the repetition in the code, by writing a single Get...() implementation that can be shared by your various types of data:
public static class Cached
{
private const string _kcountriesKey = "CountriesList";
private const string _kstatesKey = "StatesList";
private static readonly object _kcountriesLock = new object();
private static readonly object _kstatesLock = new object();
public static List<Country> GetCountriesList()
{
// Assuming SelectCountries() is in fact declared to return List<Country>
// then you should actually be able to omit the type parameter in the method
// call and let type inference figure it out. Same thing for the call to
// _GetCachedData<State>() in the GetStatesList() method.
return _GetCachedData<Country>(_kcountriesKey, _kcountriesLock, repo => repo.SelectCountries());
}
public static List<State> GetStatesList()
{
return _GetCachedData<State>(_kstatesKey, _kstatesLock, repo => repo.SelectStates());
}
private static List<T> _GetCachedData<T>(string key, object lockObject, Func<Repository, List<T>> selector)
{
List<T> cacheItem = (List<T>)HttpContext.Current.Cache[key];
if (cacheItem == null)
{
lock (lockObject)
{
// Check once more in case it got stored while waiting on the lock
cacheItem = (List<T>)HttpContext.Current.Cache[key];
if (cacheItem == null)
{
using (var repo = new Repository())
{
cacheItem = selector(repo);
HttpContext.Current.Cache.Insert(key, cacheItem, null, DateTime.Now.AddHours(2), TimeSpan.Zero);
}
}
}
}
return cacheItem;
}
// etc.
}
Finally, I'll note that since the underlying cache (i.e. System.Web.Caching.Cache) is thread-safe, you could just skip all of this altogether, and instead choose to blindly populate the cache if your item (the List<T> in question) isn't found. The only downside is that you in some cases could retrieve the same list more than once. The upside is that the code is a lot simpler.
I have the following cache implementation for my application:
public static class Keys
{
public const string CacheKey = "cachekey";
}
public interface ICache
{
string QueryCachedData(string param);
}
the data is loaded when the application starts in Global.asax
//Global.asax
protected void Application_Start(object sender, EventArgs e)
{
//instantiates the repository
HttpContext.Current.Application[Keys.CacheKey] = repository.getDataView();
}
the implementation recover the data from HttpContext.Current
public class Cache : ICache
{
private Cache() { }
private static Cache _instance = null;
public static Cache GetInstance()
{
if (_instance == null)
_instance = new Cache();
return _instance;
}
private System.Data.DataView GetCachedData()
{
if (HttpContext.Current.Application[Keys.CacheKey] == null)
{
//instantiates the repository
HttpContext.Current.Application[Keys.CacheKey] = repository.getDataView();
}
return HttpContext.Current.Application[Keys.CacheKey] as System.Data.DataView;
}
private readonly Object _lock = new Object();
public string QueryCachedData(string param)
{
lock (_lock)
{
var data = GetCachedData();
//Execute query
return result;
}
}
}
at some point i need consume some third party web service with the following class using the cache...
public class ThirdPartyWebserviceConsumer
{
ICache _cache;
int _provider;
public ThirdPartyWebserviceConsumer(int provider, ICache cache)
{
_cache = cache;
_provider = provider;
}
public result DoSomething()
{
var info = _cache.QueryCachedData(param);
}
}
...using multi-thread:
public List<Result> Foo(ICache cache, List<int> collectionOfProviders)
{
List<Result> results = new List<Result>();
List<Task> taskList = new List<Task>();
foreach (var provider in collectionOfProviders)
{
var task = new Task<Result>(() => new ThirdPartyWebserviceConsumer(provider, cache).DoSomething());
task.Start();
task.ContinueWith(task =>
{
results.Add(task.Result);
});
taskList.Add(task);
}
Task.WaitAll(taskList.ToArray());
return results;
}
My problem is that HttpContext.Current.Application is null in the thead context.
What options do I have? there are some form to access the HttpContext in thread? or maybe another type of cache that could be shared between the threads?
My problem is that HttpContext.Current.Application is null in the thead context. What options do I have?
HttpContext.Current is bound to the managed thread processing the current request.
If you need data from the current context for another thread, you need to copy that data out of the current context first and pass it to your separate thread.