using System.Reflection.Emit;
using System.Threading.Tasks;
using System.Collections.Generic;
public static void Main()
var fieldInfo = typeof(TaskScheduler).GetField("s_defaultTaskScheduler", BindingFlags.Static | BindingFlags.NonPublic);
var method = new DynamicMethod(
name: "SetSomethingElseField",
parameterTypes: new[] { typeof(TaskScheduler), typeof(TaskScheduler) },
restrictedSkipVisibility: true
var gen = method.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Stfld, fieldInfo);
var fieldSetter = (Action<TaskScheduler, TaskScheduler>)method.CreateDelegate(typeof(Action<TaskScheduler, TaskScheduler>));
fieldSetter(null, new LimitedConcurrencyLevelTaskScheduler(1));
public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
private static bool _currentThreadIsProcessingItems;
private readonly LinkedList<Task> _tasks = new LinkedList<Task>();
private readonly int _maxDegreeOfParallelism;
private int _delegatesQueuedOrRunning = 0;
public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism");
_maxDegreeOfParallelism = maxDegreeOfParallelism;
protected sealed override void QueueTask(Task task)
if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism)
++_delegatesQueuedOrRunning;
NotifyThreadPoolOfPendingWork();
private void NotifyThreadPoolOfPendingWork()
ThreadPool.UnsafeQueueUserWorkItem(_ =>
_currentThreadIsProcessingItems = true;
--_delegatesQueuedOrRunning;
item = _tasks.First.Value;
base.TryExecuteTask(item);
finally { _currentThreadIsProcessingItems = false; }
protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
if (!_currentThreadIsProcessingItems) return false;
if (taskWasPreviouslyQueued)
return base.TryExecuteTask(task);
return base.TryExecuteTask(task);
protected sealed override bool TryDequeue(Task task)
lock (_tasks) return _tasks.Remove(task);
public sealed override int MaximumConcurrencyLevel { get { return _maxDegreeOfParallelism; } }
protected sealed override IEnumerable<Task> GetScheduledTasks()
Monitor.TryEnter(_tasks, ref lockTaken);
if (lockTaken) return _tasks;
else throw new NotSupportedException();
if (lockTaken) Monitor.Exit(_tasks);