Handy Sitecore.Contex is thread-local storage, so as soon as
leave you leave sweet and warm asp.net request thread, you need to set
it up for yourself. Fortunately, it is an easy task: you should pass a
Sitecore site name to your child thread (available as
Sitecore.Site.Name
in the parent thread if you want to execute in the same site context),
and then do a
Sitecore.Context.SetActiveSite(aSiteName).
Optionally you might choose to either switch the security checks off
Sitecore.Context.Security.EnterState(SecurityState.Disabled)
or leave the security intact, pass a user name or id to your thread and do a
UserItem user = Sitecore.Context.Domain.GetUser(aUserName);
Sitecore.Context.Security.EnterUser(user);
Sites are setup in <sites> section of the web.config file,
so if you want your thread to execute in specific context with its own
settings (own database, perhaps) - set up another site in web.config
and use its name instead.
Setting up context when you spawn a new thread is rather important -
even if you don't use it directly, most of the higher-level API does.