Class TaskSchedulingThreadPool
An IThreadPool implementation which schedules tasks using a TaskScheduler (provided by implementers).
public abstract class TaskSchedulingThreadPool : IThreadPool
- Inheritance
-
TaskSchedulingThreadPool
- Implements
- Derived
- Inherited Members
Constructors
TaskSchedulingThreadPool(ILogger<TaskSchedulingThreadPool>?)
protected TaskSchedulingThreadPool(ILogger<TaskSchedulingThreadPool>? logger = null)
Parameters
loggerILogger<TaskSchedulingThreadPool>Where the pool reports what it is doing. A pool the container builds is handed the application's logger; one constructed by hand —
UseThreadPool(instance)— is handed nothing and reads LogProvider, as every pool did before.
TaskSchedulingThreadPool(int, ILogger<TaskSchedulingThreadPool>?)
protected TaskSchedulingThreadPool(int maxConcurrency, ILogger<TaskSchedulingThreadPool>? logger = null)
Parameters
maxConcurrencyintloggerILogger<TaskSchedulingThreadPool>Where the pool reports what it is doing. A pool the container builds is handed the application's logger; one constructed by hand —
UseThreadPool(instance)— is handed nothing and reads LogProvider, as every pool did before.
Properties
MaxConcurrency
Gets or sets the maximum number of thread pool tasks which can be executing in parallel.
public int MaxConcurrency { get; protected set; }
Property Value
Remarks
Once the thread pool is initialized, any attempts to change the value will be silently ignored.
PoolSize
The number of tasks that can run concurrently in this thread pool
public virtual int PoolSize { get; }
Property Value
Scheduler
Gets or sets the TaskScheduler used to schedule tasks queued by users.
public TaskScheduler Scheduler { get; protected set; }
Property Value
Remarks
Once the thread pool is initialized, any attempts to change the value will be silently ignored.
Methods
Drain(CancellationToken)
Stops the pool accepting new work, waits for the work already running to finish, and frees the pool's resources.
public 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.
GetDefaultScheduler()
Implementers should override this to provide the TaskScheduler used by their thread pool.
protected abstract TaskScheduler GetDefaultScheduler()
Returns
- TaskScheduler
The default TaskScheduler the thread pool will use if users do not specify a different TaskScheduler prior to initialization
Remarks
The TaskScheduler is provided through this factory method instead of as a property so that it can take respect MaxConcurrency changes prior to initialization time
Initialize(CancellationToken)
Initializes the thread pool for use
public virtual ValueTask Initialize(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationToken
Returns
Remarks
Note that after invoking this method, changes to MaxConcurrency and Scheduler are silently ignored.
Shutdown(bool, CancellationToken)
Stops processing new tasks and optionally waits for currently running tasks to finish.
public ValueTask Shutdown(bool waitForJobsToComplete = true, CancellationToken cancellationToken = default)
Parameters
waitForJobsToCompletebooltrue to wait for currently executing tasks to finish; otherwise, false.
cancellationTokenCancellationTokenThe cancellation instruction.
Returns
Remarks
The wait for running jobs is deliberately unbounded and not cancellable, which is what this member has always promised. Drain(CancellationToken) is the same wait with a deadline and an answer.
TryRun(Func<ValueTask>, CancellationToken)
Schedules a task to run (using the task scheduler) as soon as concurrency rules allow it.
public ValueTask<bool> TryRun(Func<ValueTask> action, CancellationToken cancellationToken = default)
Parameters
actionFunc<ValueTask>The action to be executed
cancellationTokenCancellationTokenThe cancellation instruction.
Returns
WaitForAvailableThreads(CancellationToken)
Determines the number of threads that are currently available in the pool; waits until at least one is available
public ValueTask<int> WaitForAvailableThreads(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationToken