Given the attached LINQ-Pad snippet.
It creates 8 tasks, executes for 500ms and draws a graph on when the threads were actually running.
On a 4 core CPU it may look like this:

Now, if I add a Thread.Sleep or a Task.Delay within the thread loops, I can visualize the clock of the windows system timer (~15ms):
Now, there's also the timeBeginPeriod function, where I can lower the system timer's resolution (in the example to 1ms). And here's the difference. With Thread.Sleep I get this chart (what I expected):
When using Task.Delay I get the same graph as when the time would be set to 15ms:
Question: Why does the TPL ignore the timer setting?
Here is the code (you need LinqPad 5.28 beta to run the Chart)
void Main()
{
    const int Threads = 8;
    const int MaxTask = 20;
    const int RuntimeMillis = 500;
    const int Granularity = 10;
    ThreadPool.SetMinThreads(MaxTask, MaxTask);
    ThreadPool.SetMaxThreads(MaxTask, MaxTask);
    var series = new bool[Threads][];
    series.Initialize(i => new bool[RuntimeMillis * Granularity]);
    Watch.Start();
    var tasks = Async.Tasks(Threads, i => ThreadFunc(series[i], pool));
    tasks.Wait();
    series.ForAll((x, y) => series[y][x] ? new { X = x / (double)Granularity, Y = y + 1 } : null)
        .Chart(i => i.X, i => i.Y, LINQPad.Util.SeriesType.Point)
        .Dump();
    async Task ThreadFunc(bool[] data, Rendezvous p)
    {
        double now;
        while ((now = Watch.Millis) < RuntimeMillis)
        {
            await Task.Delay(10);
            data[(int)(now * Granularity)] = true;
        }
    }
}
[DllImport("winmm.dll")] internal static extern uint timeBeginPeriod(uint period);
[DllImport("winmm.dll")] internal static extern uint timeEndPeriod(uint period);
public class Rendezvous
{
    private readonly object lockObject = new object();
    private readonly int max;
    private int n = 0;
    private readonly ManualResetEvent waitHandle = new ManualResetEvent(false);
    public Rendezvous(int count)
    {
        this.max = count;
    }
    public void Join()
    {
        lock (this.lockObject)
        {
            if (++this.n >= max)
                waitHandle.Set();
        }
    }
    public void Wait()
    {
        waitHandle.WaitOne();
    }
    public void Reset()
    {
        lock (this.lockObject)
        {
            waitHandle.Reset();
            this.n = 0;
        }
    }
}
public static class ArrayExtensions
{
    public static void Initialize<T>(this T[] array, Func<int, T> init)
    {
        for (int n = 0; n < array.Length; n++)
            array[n] = init(n);
    }
    public static IEnumerable<TReturn> ForAll<TValue, TReturn>(this TValue[][] array, Func<int, int, TReturn> func)
    {
        for (int y = 0; y < array.Length; y++)
        {
            for (int x = 0; x < array[y].Length; x++)
            {
                var result = func(x, y);
                if (result != null)
                    yield return result;
            }
        }
    }
}
public static class Watch
{
    private static long start;
    public static void Start() => start = Stopwatch.GetTimestamp();
    public static double Millis => (Stopwatch.GetTimestamp() - start) * 1000.0 / Stopwatch.Frequency;
    public static void DumpMillis() => Millis.Dump();
}
public static class Async
{
    public static Task[] Tasks(int tasks, Func<int, Task> thread)
    {
        return Enumerable.Range(0, tasks)
            .Select(i => Task.Run(() => thread(i)))
            .ToArray();
    }
    public static void JoinAll(this Thread[] threads)
    {
        foreach (var thread in threads)
            thread.Join();
    }
    public static void Wait(this Task[] tasks)
    {
        Task.WaitAll(tasks);
    }
}


