A question that has come up as part of that other one, related to the tuning of the "multiprogramming level" (MPL) in SA 12 and above and the usage of external environments:
Tasks typically service user requests. So setting the maximum MPL to 80 would mean the database server can handle up to 80 active requests concurrently - if there are more requests those will be queued.
To cite from the v16 docs on Threading behavior:
What other kind of tasks may use workers from the worker thread pool?
asked 01 Jun '15, 04:12
FWIW I do remember this being covered some place before, in a response? ... or a whitepaper? If I find that I will link it in later.
The various -gn* switches controls the number of workers and your question is actually about workers. In contrast sa_conn_info() shows information only about connections (connection contexts for both the external and internal contexts). There is not a 1-to-1 mapping between those concepts. Tasks is what is actually mapped onto workers and it is a 1 to optionally-many relationship at both levels here.
Connections (internal or external) are optionally mapped onto 1 or more Tasks (when there is an active query/operation) and Tasks (when scheduled) are mapped to Workers. Needless to say unscheduled tasks do not currently consume a worker. If a task needs a connection-context there will be a trackable connection for that (I don' know of any exceptions to that rule).
Of course it is workers that are eventually scheduled on actual system threads (in the typical SMP and OS-specific way) running on some core.
As to what consumes the extra workers you are worried about?
When you use external functions/procedures of any kind (Not the old school DLL calls but the newer external environments of any sort) or remote server accesses (remote procedure call or accessing proxy tables) those do involve extra workers (typically 1 per external reference so there could be multiple per query). These execute on the same connection context as the triggering internal/external connection so they do not show up as extra internal connections. For remote server connections those extra connections will show up on the remote server but not the caller system. For the per-database external environments (Java or CLR) there will be an extra connection for the call back mechanism used for that; I'd have to check on per-connection external environments.
All of this is in addition to the workers used for parallelism which do show up as extra internal connection contexts in addition to the extra workers involved (not all of which may be consuming an actual worker if not scheduled).
Not all connections consume a worker at any moment in time. Connections without requests (and possibly internal parallel worker connections that don't execute a parallel sub-plan due to runtime adjustments) do not tie up a worker. But connections can often be associated with multiple workers when doing something complex using multiple features.
Events, cleaner, stats cleaning, ... have their on internal connections (as you've already noted) and tasks and workers when running ...
Of course I haven't yet covered HTTP requests (yep 1 connection and 1 worker) or remote HTTP requests (yep an additional 1 worker on the connection context) and of course HTTP requests operate over queries, functions, procedures, . . . and there can be a fan-out there ... again.
Did I miss anything else?
The basic link for the this "threading model" is in every DCX edition. I don't find any official break down on the various kinds of tasks nor a counter for that. People do track the current level of utilization of workers by monitoring the Unscheduled Requests and Active Requests but those are best used for performance impact/efficiency measurements; not so helpful for breaking out or enumerating the current break down on what those tasks are. Combining those with the sa_conn_activity()/info() information gets you a little closer.
I just added the link to active requests before I noticed your latest post but you are correct! According to that DCX article it is only workers assigned to client-side requests contribute to the ActiveReq counter. It is also underscored by this other article too.
They do consume workers and that will affect the way things get optimized (if parallelism is your concern), scheduled, or delayed if unscheduled (but maybe not counted if not from a user request).