Short answer
In general they all seem to be using Sitecore.Context.Items
underneath to store the state, which would make them all request-scoped, being dependent on the current HttpContext
.
When HttpContext.Current
is null
thena static Sitecore.ContextCaching.Items
falls back to using thread local storage. So without an HttpContextItemsContext
they become thread-scopedobject.
(I'm not 100% confident on all this threading stuff, so anyone please correct me if I'm wrong)
Detailed answer
Most of the switchers/disablers inherit from Sitecore.Common.Switcher<TValue, TSwitchType>ItemsContext
class, which uses the curret Sitecore.Context.ItemsHttpContext
to store the stateif it's available (as a stack of the switched values, in case it's used multiple timesmaking it request-scoped).
Sitecore.Context.Items
under the covers uses either HttpContext.Current.Items
or if that isotherwise a nullprivate static IDictionary
then falls back tomarked with the Sitecore.Threading.ThreadData.GetData("sc_items")[ThreadStatic]
attribute (thread local storagemaking it thread-scoped).
namespacepublic Sitecore.Threadingclass ItemsContext : IDictionary, ICollection, IEnumerable
{
public[ThreadStatic]
class ThreadData private static IDictionary dictionary;
{protected virtual IDictionary Dictionary
{
public static object GetData(string key)get
{
LocalDataStoreSlotHttpContext namedDataSlotcurrent = ThreadHttpContext.GetNamedDataSlot(key);Current;
if (namedDataSlotcurrent != null)
return Threadcurrent.GetData(namedDataSlot);Items;
return ItemsContext.dictionary ?? (objectItemsContext.dictionary = (IDictionary) null;new Hashtable());
}
}
public static void SetData(string key, object data)
this[string key]
{
get { return Thread.SetData(Threadthis.GetNamedDataSlotDictionary[(keyobject) ?? Thread.AllocateNamedDataSlot(key),key]; data);}
}
set { this.Dictionary[(object) key] = value; }
public class Keys}
// ...
}
If they are thread specific, then what advice is there for using them in a multi-threaded scenario? In a parallel loop, should I create the switchers/disablers inside each 'iteration'?
When running things in parallel using Parallel.Foreach
you would have to use the switcher/disabler inside the loop as they run on separate threads.
Parallel.ForEach(source, x =>
{
using (new SecurityDisabler())
public const{
string Items = "sc_items";
// Run your code }here
}
});
##ExamplesAs Mark Cassidy also mentions in most cases I don't think there would be much or any gain in running stuff in parallel when accessing anything related to the Sitecore context as you would most likely be I/O limited anyway.
There might be a few usecases where it could make sense, but generally I probably would recommend against it.
Some more background info
Most of types inheritingthe switchers/disablers inherit from Sitecore.Common.Switcher<TValue, TSwitchType>
: class, which uses Sitecore.Context.Items
to store the state (as a stack of the switched values, in case it's used multiple times).
Some other types uses a custom implementation and just inherits IDisposable
.
Examples of types inheriting Switcher<TValue, TSwitchType>
:
##Examples of custom implementations only inheriting IDisposable
: