Does hangfire use .NET ThreadPool internally?


#1

When I work with threadstatic variables in my background jobs , strange things happen on the production system which is has more than 15 queues and 40 workers.

I think this is because of the ThreadPool is used internally as stated below

http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx

When the thread pool reuses a thread, it does not clear the data in thread local storage or in fields that are marked with the ThreadStaticAttribute attribute. Therefore, data that is placed in thread local storage by one method can be exposed to any other method that is executed by the same thread pool thread. A method that accesses a field that is marked with the ThreadStaticAttribute attribute could encounter different data depending on which thread pool thread executes it.

Can somebody confirm that or do you have any explanation?

Thanks…


#2

Maybe I have the correct response:
In case you you use async/await methods, you cannot use ThreadStatic.
In other cases, if i’m correct, Hangfire uses a private set of threads, so it’s probably that a ThreadStatic variable will be reused, just like if you use ThreadPool.


#3

Hangfire uses dedicated threads for synchronous jobs, but async jobs are still executed on the thread pool.
Thread-local variables are working the same way for all threads, be it dedicated or thread pool threads. Once set, they retain their values and are available to any code executed on that thread.

With sync code, it is unlikely you’ll need to share values between jobs the worker thread may execute.
With async, the method may continue on another thread, so it is dangerous and error-prone to use thread-local variables.

Avoid using them at all, unless you are 200% sure you need them.


#4

Hangfire uses dedicated threads for synchronous jobs: pretty sure it is false.

The code is using this:
return Task.Factory.StartNew(
() => RunProcess(process, context),
TaskCreationOptions.LongRunning);

And without providing a TaskScheduler to the StartNew method, it fallback on the ThreadPoolTaskScheduler


#5

Note the TaskCreationOptions.LongRunning which starts a dedicated thread for the task (at least in existing implementations).