Interface IThreadPool
- Namespace
- Quartz.Extensibility
- Assembly
- Quartz.dll
The interface to be implemented by classes that want to provide a thread pool for the IScheduler's use.
public interface IThreadPool
Remarks
IThreadPool implementation instances should ideally be made for the sole use of Quartz. Most importantly, when the method WaitForAvailableThreads(CancellationToken) returns a value of 1 or greater, there must still be at least one available thread in the pool when the method TryRun(Func<ValueTask>, CancellationToken) is called a few moments (or many moments) later. If this assumption does not hold true, it may result in extra JobStore queries and updates, and if clustering features are being used, it may result in greater imbalance of load.
Properties
PoolSize
Get the current number of threads in the IThreadPool.
int PoolSize { get; }
Property Value
Methods
Drain(CancellationToken)
Stops the pool accepting new work, waits for the work already running to finish, and frees the pool's resources.
ValueTask<bool> Drain(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenCancels the wait, not the running work.
Returns
- ValueTask<bool>
true if the work that was running finished; false if
cancellationTokenfired first and work is still running.
Remarks
The bounded form of Shutdown(bool, CancellationToken) with waitForJobsToComplete: true: the wait
ends when cancellationToken fires, and the outcome is reported rather than
thrown. That is what lets a caller say "drain, but give up after this long" and still carry on
with the rest of its own shutdown — which Shutdown(bool, CancellationToken) cannot express, because a wait
it abandoned by throwing would skip everything the caller still has to tear down.
The wait must not block the calling thread. Callers include a host's graceful-shutdown path, and an implementation that blocks pins a thread for as long as the slowest job runs.
Giving up abandons the wait, never the work: running work is not cancelled, because the pool has no means to interrupt it and whether a shutting-down scheduler interrupts its jobs is ShutdownJobInterruption's decision, already made by the time this is called. The pool is left shut down either way, so the answer says what was true when it stopped waiting, not what the caller should do about it.
The barrier has to cover everything a work item does, and not merely the part of it a caller can see: TryRun(Func<ValueTask>, CancellationToken) is handed the whole of a job's execution, of which the last act is the job store update that completes the trigger. A pool that waits for its work items therefore waits for those writes too — which a count of executing jobs does not, since a job leaves that count before its store update is issued.
The default implementation calls Shutdown(bool, CancellationToken) with waitForJobsToComplete: true,
whose wait cannot be given up on, and so it can only report that it drained. That keeps a pool
written before this member existed correct rather than fast; override it to honour a deadline.
Initialize(CancellationToken)
Must be called before the thread pool is used, in order to give the it a chance to Initialize.
ValueTask Initialize(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenThe cancellation instruction.
Returns
Remarks
Typically called by the ISchedulerFactory.
Shutdown(bool, CancellationToken)
Called by the QuartzScheduler to inform the thread pool that it should free up all of it's resources because the scheduler is shutting down.
ValueTask Shutdown(bool waitForJobsToComplete = true, CancellationToken cancellationToken = default)
Parameters
waitForJobsToCompleteboolWhether to wait for executing jobs to finish first.
cancellationTokenCancellationTokenThe cancellation instruction.
Returns
TryRun(Func<ValueTask>, CancellationToken)
Schedules the given work to run as soon as the pool's concurrency rules allow it.
ValueTask<bool> TryRun(Func<ValueTask> action, CancellationToken cancellationToken = default)
Parameters
actionFunc<ValueTask>The work to run.
cancellationTokenCancellationTokenThe cancellation instruction.
Returns
- ValueTask<bool>
true if the work was scheduled; otherwise, false (the pool has been shut down or was never initialized).
Remarks
The implementation of this interface should not throw exceptions unless there is a serious problem (i.e. a serious misconfiguration). If there are no available slots, rather it should either queue the action, or wait until a slot is available, depending on the desired strategy.
WaitForAvailableThreads(CancellationToken)
Determines the number of execution slots that are currently available in the pool. The scheduler uses the count to size the batch of triggers it acquires next.
ValueTask<int> WaitForAvailableThreads(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenThe cancellation instruction.
Returns
Remarks
The implementation of this method should wait until there is at least one available slot. It is awaited by the scheduler's own loop, so an implementation must not block the calling thread while it waits.