HttpContext Class and its Thread Safety - c#

I have an Singleton object in application that has following property:
private AllocationActionsCollection AllocationActions
{
get
{
return HttpContext.Current.Session["AllocationOptions.AllocationActions"] as AllocationActionsCollection;
}
set
{
HttpContext.Current.Session["AllocationOptions.AllocationActions"] = value;
}
}
I'm dealing with one error (HttpContext.Current.Session["AllocationOptions.AllocationActions"] is null even though it is supposed to me always set to valid instance...). I just read in MSDN that HttpContext instance member are not guaranteed to be thread safe! I wonder if that could be the issue. There could be a resources race somewhere in application and the moment where HttpContext.Current.Session["AllocationOptions.AllocationActions"] is null is the moment where AllocationActions setter is used using this statement:
AllocationActions = new AllocationActionsCollection(Instance.CacheId);
My questions are:
a) I'm shocked that HttpContext.Current.Session is not thread safe. How to safely use that property then?
b) do you have any ideas why that Session variable can be null (even though I'm pretty sure I'm setting it before it's used for the first time)?
Thanks,Pawel
EDIT 1:
a) line that initializes session variable is set every 2 minutes with following statement (executed in Page_Load)
AllocationActions = new AllocationActionsCollection(Instance.CacheId);
b) code that calls getter is called in event handlers (like Button_Click)
c) there is not custom threading in application. only common HTTP Handler

A singleton object is realized by restricting the instantiation of a class to one object.
HttpContext.Current.Session is an area dedicated to a single user; any object stored in Session will be available only for the user/session that created it.
Any object stored in Application will be available only for every user/session.
Any static object also, will be available only for every user/session. Suggested implementations always use static objects.. why didn't you?

HttpContext.Current returns a separate HttpContext instance for each request. There can be multiple threads processing requests, but each request will get its own HttpContext instance. So any given instance is not being used by multiple threads, and thread safety is not an issue.
So unless you're manually spinning up multiple threads of your own for a single request, you are threadsafe.

The thread safety of the HttpContext class is pretty standard for .NET. The basic rule of the thumb (unless explicitly specified) is that static members are thread safe and instance members aren't.
In any case it is hard to tell why your session variable is null without looking more into the code that sets/resets it. Or perhaps you are calling your get_AllocationActions method from a different session than the one you set it in. Again, more code would help.

To access the session property safely you would just wrap the access in a lock statement and use the SyncRoot object of the session class.

Related

Locking for each property

I'm looking at some code that I don't understand the point of.
private object myProperty_lock = new Object();
private SomeType myProperty_backing;
public SomeType MyProperty
{
get { lock(myProperty_lock) { return myProperty_backing; } }
set { lock(myProperty_lock) { myProperty_backing = value; } }
}
This pattern is used many times within the same class.
Each time this pattern is used, there's a new lock object. (It's not a shared lock object for all properties.)
The types used are reference types and primitives. (No non-primitive structs.)
Does this code do anything? References & primitives are assigned atomically, so we don't need to protect against a thread switch in the middle of the assignment. The lock object isn't used anywhere else, so there's no protection there.
Is there something with memory barriers, perhaps? I had assumed that a lock inside a method didn't affect things outside of that method.
The fact that code is inside a method does not imply a memory barrier. So you may be on the right track for suspecting that the locks are for that fresh read memory guarantees.
Of course it also could have been added due to the person adding it was a cargo cult programmer and did not understand why to do it and only did it because he saw a code example that does it.
The problem I see here is that by using lock the developer indicates a concern regarding thread safety. They thought that concurrent threads might be accessing this property.
My first question would be whether that's actually the case - is there concurrent access to this property?
There might be a valid scenario, but is there a reason why any number of threads might be able to set that reference? What sort of logic is happening if one thread sets the property, presumably for some valid reason, only to have it immediately overwritten by another thread? How is the application doing something predictable? Did the reference set by the previous caller just not matter? Then why did it set the property?
And what about the object - SomeType - returned from the property? Now any number of threads can have a reference to the same instance. Can SomeType can be altered, and if so, is it thread safe?
I normally wouldn't wonder, but when I see something that looks odd with multithreading I like to dig a little deeper. Maybe they have it all patched together and it works, but sometimes they don't.

HttpContext.Current.Session null after making method async

I had a method like below
book.Bindbook();
I made it async as follow
new Task(book.Bindbook).Start();
Now this method uses HttpContext.Current.Session which is now returning null.
Here is code that returns null
public static Bookmanager CartManager
{
//Gets the value from the session variable.
get
{
try
{
if (HttpContext.Current.Session["BookData"] == null)
{
Bookmanager bookmgr= new Bookmanager ();
Book book = new Book(SessionManager.CurrentUser);
bookmgr.SetCurrentCart(book);
HttpContext.Current.Session["BookData"] = bookmgr;
}
else if (((Bookmanager)HttpContext.Current.Session["BookData"]).GetCurrentCart() == null)
{
Book book = new Book(SessionManager.CurrentUser);
((Bookmanager)HttpContext.Current.Session["BookData"]).SetCurrentCart(book);
}
}
catch(Exception ex)
{
//throw ex;
}
return ((Bookmanager)HttpContext.Current.Session["BookData"]);
}
//Sets the value of the session variable.
set
{
HttpContext.Current.Session["BookData"] = value;
}
}
There's a lot of potential problems with your solution which have lead to this problem. I'll try to break it down into pieces to explain what's going on.
new Task(book.Bindbook).Start() doesn't always run where you think it does
This method of creating an asynchronous operation is subtly dangerous as it's not easy to know how the task will be executed. When you call this constructor, the Task will capture the TaskScheduler.Current value as the mechanism it will use to schedule it's own execution. This means that your task's execution is invisibly tied to the context it's in.
Typically, you want to use Task.Run(Action) instead of creating a new Task instance and then calling Start, as this always runs on the value of TaskScheduler.Default, which is usually the .NET thread pool and is generally what you want to do when running a background task.
HttpContext is not thread-safe
The HttpContext class was never intended to be called from multiple threads safely. It's Current value tied to the thread which is processing the request and is not available on other threads. You should not pass it to other threads. Generally-speaking you should reduce the surface-area of HttpContext in your applications to a bare minimum. It's nearly impossible to mock for testing purposes and has several subtle limitations (such as you are finding) which make it challenging to work with.
Instead, surface the Current value as early as possible in your code and keep a reference to the objects you actually need to work with (like the session).
Static properties are usually harmful
Having a static property on an object either means that there are exactly one of these things for the entirety of the AppDomain (such as TaskScheduler.Default) where they represent some cross-cutting concern that can be configured, or that there is some hidden context manipulating the value behind the scenes. The former case is rare, but can be acceptable in some cases, but the second is pretty harmful. HttpContext.Current is an example of a value that should not be static (and future version of ASP.NET do away with it entirely). It makes code hard to reason about, nearly impossible to test and introduces subtle bugs (like this one) which can't easily be dealt with.
Fundamentally, this is the biggest problem here and the root cause of your pain. If this property were exposed as an instance property and the instance was scoped to the request context, you would have none of your issues. Once you're working with an object whose lifetime is the same as your request, all your critical state becomes local and easy to reason about.
Use ConfigureAwait(true) to allow to continue on the original context.
var task = new Task(() => book.Bindbook()).ConfigureAwait(true);
task.Start();
HttpContext is bound to thread, that's why it is null.
I think better solution will be to pass all needed data through parameters to other thread and not sharing HttpContext.

What is exactly a "thread-safe type"? When do we need to use the "lock" statement?

I read all documentation about thread-safe types and the "lock" statement, but I am still not getting it 100%.
When exactly do I need to use the "lock" statement? How it relates to (non) thread-safe types? Thank you.
Imagine an instance of a class with a global variable in it. Imagine two threads call a method on that object at exactly the same time, and that method updates the global variable inside.
The likelihood is that value in the variable will get corrupted. Different languages and compilers/interpreters will deal with this in different ways (or not at all...) but the point is that you get "undesired" and "unpredictable" results.
Now imagine that the method obtains a "lock" on the variable before attempting to read from or write to it. The first thread to call the method will get a "lock" on the variable, the second thread to call the method will have to wait until the lock is released by the first thread. While you still have a race condition (i.e. the second thread might overwrite the value from the first) at least you have predictable results because no two threads (that are unaware of each other) can modify the value at the same time.
You use the lock statement to obtain that lock on the variable. Typically you'd define a separate object variable and use that for the lock object:
public class MyThreadSafeClass
{
private readonly object lockObject = new object();
private string mySharedString;
public void ThreadSafeMethod(string newValue)
{
lock (lockObject)
{
// Once one thread has got inside this lock statement, any others will have to wait outside for their turn...
mySharedString = newValue;
}
}
}
A type is deemed "thread-safe" if it applies the principle that no corruption will occur if shared data is accessed by multiple threads at the same time.
Beware the difference between "immutable" and "thread-safe". Thread-safe says that you have coded for the scenario and won't get corruption if two threads access shared state at the same time, whereas immutability is simply saying you return a new object rather than modifying it. Immutable objects are thread-safe, but not all thread-safe objects are immutable.
Thread safe code means code that can be accessed with many threads and still operate correctly.
In C#, this normally requires some sort of synchronization mechanism. A simple one is the lock statement (which is behind the scenes a call to Monitor.Enter). A code block that is surrounded by a lock block can only be accessed by one thread at a time.
Any use of a type that is not thread safe requires you to manage synchronization yourself.
A good resource to learn about threading in C# is the free eBook by Joe Albahari, found here.
http://en.wikipedia.org/wiki/Thread_safety

Thread safety across shared instances (C#)

I use a factory pattern to create a custom object which is loaded from a cache if possible.
There are no static members or functions on the custom object.
Assuming 2 threads call the factory and are both returned references to the same object from the cache. (i.e. No new operator, in ref to answer below, object returned from a collection)
If I want to modify a private instance member on inside the class:
a) Shoulb I lock it first?
b) Will the change be reflected in both threads?
I assume yes for both questions, but at the same time it feels like the threads have different instances of the class.
Have I must something fundamental here? Why do I feel like I have?
===============
Following the first few answers I have confirmed what I thought, thanks.
I guess what I really want to know is, if the objects are pretty much only read-only, i.e. after being created they only have one instance member that can change, do I need to do any locks when reading properties that are not affected by that one changeable instance member?
Again I assume no, but I have to come to value the second-opinion of the collective StackOverflow brains trust :)
Reading and writing of most primitive types, string and object references is atomic (everything except non-volatile longs and doubles). This means locks are not necessary if you are simply reading or writing a field or other variable in isolation. So, if you ever see code like this (and I guaranteee you will), you can happily strip out the unnecessary and costly locking:
public SomeClass SomeProperty
{
get
{
lock (someLock)
{
return someField;
}
}
set
{
lock (someLock)
{
someField = value;
}
}
}
If, however, you want to change the value, increasing it by one for example, or if you want to read multiple, related variables then you need to lock if you want sensible results.
It is also worth noting that the Hashtable and Dictionary support mulitple concurrent readers without the need for any kind of locking.
You are assuming that the threads have different instances of the object, which is incorrect. The threads are pointing to the same object; therefore, you have to synchronize access to any members that might be accessed by multiple threads, whether it be through property accesses, method calls, etc, etc.
It should be the same object, and the answer to your questions is YES, YES.
How do you check that there are 2 instances?
Yes, you should lock before setting the private member. This will be reflected in both threads (since they're the same object).
However, you may want to take some time to consider how to handle the locks and threading.
If your factory is creating the object and adding it to the collection, it will need a lock of some form around the routine to create the object. Otherwise, it's possible that the two threads could ask for the object at the same time, before it was created, and create 2 instances.
Also, I wouldn't recommend setting the private member directly - it would be a good idea to have a single object inside of the returned class instance used just for locking, and use some form of accessor (method or property) that locks on that synchronization object and then sets the field.
As for not "trusting" that its two instances - you can always just do something to check in the debugger. Add a check for reference equality, or even temporarily add a GUID to your class that's setup at construction - it's easy to verify that they're the same that way.
If the new operator or the constructor is getting called twice on the object, then you have yourself two instances of the same class.
Do you need both threads to see the results of changing the private member? Or is it perfectly OK with you if both threads get the object, but when one thread changes a private member, the other thread doesn't see that change?
Here's why I ask: In your factory, you could take the object from cache and then clone or copy it before returning it. As a result, each thread would have its own copy of the class, and that copy would have the state that was in the cached object at the time they asked for it. No 2 threads would ever share the exact same instance, because you're making a copy for each thread.
If that fits your requirements, then you can avoid having to lock the object (you will need synchronization on the factory method itself though ... which you also need in your current case).
Be careful with the idea of a "clone", however. If you have a graph of objects and you only do a shallow clone, you'll wind up with references that are still shared across threads, forcing you to need synchronization again. This idea of one-copy-per-thread makes best sense if the object is a very simple object without a lot of references to other objects.

Difference between lock(locker) and lock(variable_which_I_am_using)

I'm using C# & .NEt 3.5. What is the difference between the OptionA and OptionB ?
class MyClass
{
private object m_Locker = new object();
private Dicionary<string, object> m_Hash = new Dictionary<string, object>();
public void OptionA()
{
lock(m_Locker){
// Do something with the dictionary
}
}
public void OptionB()
{
lock(m_Hash){
// Do something with the dictionary
}
}
}
I'm starting to dabble in threading (primarly for creating a cache for a multi-threaded app, NOT using the HttpCache class, since it's not attached to a web site), and I see the OptionA syntax in a lot of the examples I see online, but I don't understand what, if any, reason that is done over OptionB.
Option B uses the object to be protected to create a critical section. In some cases, this more clearly communicates the intent. If used consistently, it guarantees only one critical section for the protected object will be active at a time:
lock (m_Hash)
{
// Across all threads, I can be in one and only one of these two blocks
// Do something with the dictionary
}
lock (m_Hash)
{
// Across all threads, I can be in one and only one of these two blocks
// Do something with the dictionary
}
Option A is less restrictive. It uses a secondary object to create a critical section for the object to be protected. If multiple secondary objects are used, it's possible to have more than one critical section for the protected object active at a time.
private object m_LockerA = new object();
private object m_LockerB = new object();
lock (m_LockerA)
{
// It's possible this block is active in one thread
// while the block below is active in another
// Do something with the dictionary
}
lock (m_LockerB)
{
// It's possible this block is active in one thread
// while the block above is active in another
// Do something with the dictionary
}
Option A is equivalent to Option B if you use only one secondary object. As far as reading code, Option B's intent is clearer. If you're protecting more than one object, Option B isn't really an option.
It's important to understand that lock(m_Hash) does NOT prevent other code from using the hash. It only prevents other code from running that is also using m_Hash as its locking object.
One reason to use option A is because classes are likely to have private variables that you will use inside the lock statement. It is much easier to just use one object which you use to lock access to all of them instead of trying to use finer grain locks to lock access to just the members you will need. If you try to go with the finer grained method you will probably have to take multiple locks in some situations and then you need to make sure you are always taking them in the same order to avoid deadlocks.
Another reason to use option A is because it is possible that the reference to m_Hash will be accessible outside your class. Perhaps you have a public property which supplies access to it, or maybe you declare it as protected and derived classes can use it. In either case once external code has a reference to it, it is possible that the external code will use it for a lock. This also opens up the possibility of deadlocks since you have no way to control or know what order the lock will be taken in.
Actually, it is not good idea to lock on object if you are using its members.
Jeffrey Richter wrote in his book "CLR via C#" that there is no guarantee that a class of object that you are using for synchronization will not use lock(this) in its implementation (It's interesting, but it was a recommended way for synchronization by Microsoft for some time... Then, they found that it was a mistake), so it is always a good idea to use a special separate object for synchronization. So, as you can see OptionB will not give you a guarantee of deadlock - safety.
So, OptionA is much safer that OptionB.
It's not what you're "Locking", its the code that's contained between the lock { ... } thats important and that you're preventing from being executed.
If one thread takes out a lock() on any object, it prevents other threads from obtaining a lock on the same object, and hence prevents the second thread from executing the code between the braces.
So that's why most people just create a junk object to lock on, it prevents other threads from obtaining a lock on that same junk object.
I think the scope of the variable you "pass" in will determine the scope of the lock.
i.e. An instance variable will be in respect of the instance of the class whereas a static variable will be for the whole AppDomain.
Looking at the implementation of the collections (using Reflector), the pattern seems to follow that an instance variable called SyncRoot is declared and used for all locking operations in respect of the instance of the collection.
Well, it depends on what you wanted to lock(be made threadsafe).
Normally I would choose OptionB to provide threadsafe access to m_Hash ONLY. Where as OptionA, I would used for locking value type, which can't be used with the lock, or I had a group of objects that need locking concurrently, but I don't what to lock the whole instance by using lock(this)
Locking the object that you're using is simply a matter of convenience. An external lock object can make things simpler, and is also needed if the shared resource is private, like with a collection (in which case you use the ICollection.SyncRoot object).
OptionA is the way to go here as long as in all your code, when accessing the m_hash you use the m_Locker to lock on it.
Now Imagine this case. You lock on the object. And that object in one of the functions you call has a lock(this) code segment. In this case that is a sure unrecoverable deadlock

Categories