Open ReubenBond opened 5 years ago
In theory I'm not against the idea of a TaskScheduler.SetCurrent. In practice I'm not sure how it would work, at least not without an overhaul of this area of tasks. Today TaskScheduler.get_Current is effectively just:
Task t = Task.CurrentTask; // gets whatever innermost Task is currently executing on this thread
return t?.Scheduler ?? TaskScheduler.Default;
so there isn't really a notion of a stored current scheduler like you'd need to implement SetCurrent. Someone would need to prototype this in corelib to get a sense for the implications... I don't know if it'd end up being trivial or a rewrite or somewhere in between.
Orleans is one of the (seemingly few) frameworks which makes heavy use of custom
TaskScheduler
s. We use them to implement single-threaded execution for grains (~distributed objects). Each grain has its ownActivationTaskScheduler
, so there may be 10^5 or 10^6TaskScheduler
instances in a process at any one time (on the high end).ActivationTaskScheduler
is a wrapper aroundWorkItemGroup
, a collection of work items to execute serially. When a work item (eg, aTask
) is scheduled, theWorkItemGroup
itself is scheduled onto a dedicated thread pool for execution. This is very similar toIThreadPoolWorkItem
, so there's room for us to supportIThreadPoolWorkItem
and also use the default thread pool in future. EDIT 2021: ThoseWorkItemGroup
instances are now scheduled on theThreadPool
viaIThreadPoolWorkItem
.Each grain sends/receives calls via RPC interfaces. We schedule those messages onto the grain's
WorkItemGroup
, but we have to wrap these work items in aTask
so we can maintain single-threadedness in the case that the user's code doesn't complete synchronously or kicks off some background work (fire-and-forget style). For example, aJoinGame(id)
call might contact some other grains and write to storage. This wrapping is not ideal.If we could set & reset
TaskScheduler.Current
from within ourWorkItemGroup
then we could avoid this wrapping while still being able to have single-threadedness.Is exposing a
TaskScheduler.Current
setter a possibility? Failing that, what other options should we consider?I recognize potential pitfalls associated with broadly exposing a setter for
TaskScheduler.Current
. If that is a major concern then perhaps we could expose some scary-looking API likeTaskScheduler.UnsafeSetCurrent(TaskScheduler)
or some alternative means to control the ambient scheduler which doesn't require allocating a task.