What is the recommended way to process Jobs at a lower priority?

I am building a web application and I want to use Hangfire to process long running calculations outside of the request context.

So, the basic scenario is this:

  • user enters input;
  • input is stored in a DB, under an id;
  • job is enqueued with parameter this id;
  • when the job is started, it will:
    ** retrieve input;
    ** start calculations;
    ** store results in DB;
    ** mark done;
  • meanwhile, the UI polls for results;
    ** when done, show results.

Since there are few concurrent users expected, we do not want to invest in running separate servers with a worker services. So, Hangfire is running in process with the web server. It is OK if users need to wait longer, whenever the queue is full.

The calculations are CPU bound. To avoid the web server to become unresponsive, I could limit the number of background worker to below the number of cores in the server. Would that work?

However, it may be more appropriate to use: Thread.Priority Property, to lower the priority:
System.Threading.Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;

My questions:

  1. Are any issues to be expected?
  2. Does Hangfire have any mechanism to specify the ThreadPriority of the jobs it starts?

If you wanted to implement it in a cross-cutting concerns manner the first thing that comes to mind is that Hangfire appears to be very open/extensible. If you can override/extend the default implementation and then ‘plug in’ your custom one you could use whatever means to identify the priority you want to assign to the ‘running’ thread for job. At least from my limited exposure that’s the first thing I thought of.

Of course, having that as an inherent feature would be nice as part of the job registration (or better yet when enqueuing the work and use the definition from the job as a default when not specified, etc).

One observation I have of these type of job registration & related features is that there’s a tendency to do so via use of Attributes which works for a majority of cases, but when using dynamic or data-driven approaches there seems to be gaps in what you can & cannot do job type registration wise; Or I just haven’t found the right ways.