Fine, I'll be the one to jump in and tell you what no one wants to hear ;-)
Sitecore.Context is an anti-pattern
I've argued this before, and I stand by it. The problems around this particular implementation pattern are many - personally I dislike it because it's more or less the exact opposite of Dependency Injection. And because of that, it makes achieving Inversion of Control all but impossible.
And that's what the Switchers
(the examples above are all, in one form or another, based on a Switcher mechanic inside Sitecore) are. Mechanisms that attempt to give you (the caller of the API) back some control, against a rogue codebase that cherry picks whatever data it needs in Context.this and Context.that.
Now I understand why it was done this way. At least when I put on my 2003 glasses and the software landscape back then. Performance, lack of DI frameworks, overall maturity of the development practices and community.
But take these two examples (hand crafted, they may not compile):
public IEnumerable<INews> GetLatest3NewsArticles()
{
// this could just as easily have been Sitecore.Context.NewsRepository
var newsRepository = DependencyResolver.Resolve<INewsRepository>();
var newsList = newsRepository.GetAll().Where(n => n.Language.Name == Sitecore.Context.Language.Name
&& n.InnerItem.Axes.IsDescendantOf(Sitecore.Context.Site.StartItem).Take(3);
return newsList;
}
And compare it to this:
public IEnumerable<INews> GetLatest3NewsArticles(INewsRepository newsRepository, Item siteRoot)
{
var newsList = newsRepository.GetAll().Where(n => n.Language.Name == siteRoot.Language.Name
&& n.InnerItem.Axes.IsDescendantOf(siteRoot).Take(3);
return newsList;
}
Now none of these are particularly good examples of code one would actually implement. But the key difference between them is; one uses Inversion of Control. It is controlled entirely by parameters that are sent to it. The other... well it's just sad. It can only be controlled from the outside, by controlling what dependency gets resolved, switching Context Language, switching Context Site.
And this is why you need Switchers. For Sitecore Code. For your own code, however, in my opinion there is no excuse. Your code should be more like example 2 above, and not like example 1.
So yes, the Switchers apply to current thread
Which is also why various multithreading scenarios are hard to do in Sitecore. Think Kam's experiments with async Controllers, as just one example. Or what you experience yourself now, trying to run migration code under Parallels
.
But to come back to your question - the advise for using Switchers in a multi-threaded scenario? Don't. That's the advise. Design your code differently.
For this and any code you make, maintain Inversion of Control and don't write methods that rely on Sitecore.Context, Global Variables, or anything other than what they explicitly ask for in the method parameters. It's bad design and it's even worse encapsulation.