Skip to content

Instantly share code, notes, and snippets.

@svick
Last active August 29, 2015 14:08
Show Gist options
  • Select an option

  • Save svick/251f233d856a763fcf16 to your computer and use it in GitHub Desktop.

Select an option

Save svick/251f233d856a763fcf16 to your computer and use it in GitHub Desktop.
Proving that the Task dispatching loop doesn't wait for thread scheduling quantum
using System;
using System.Diagnostics;
using System.Threading.Tasks;
class Program
{
private static void Main()
{
MainAsync().Wait();
}
private static async Task MainAsync()
{
var sw = new Stopwatch();
sw.Start();
for (int i = 1; i <= 100; i++)
{
await PreciseTimer.Delay(1);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); // 103 ms
sw.Restart();
for (int i = 1; i <= 100; i++)
{
await Task.Delay(1);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); // 1544 ms
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
// this is extremely wasteful, but that doesn't matter here
static class PreciseTimer
{
static PreciseTimer()
{
var thread = new Thread(TimerMethod);
thread.IsBackground = true;
thread.Start();
}
private static object Lock = new object();
private static DateTime? FireTime = null;
private static Action Action = null;
private static void TimerMethod()
{
while (true)
{
Action a = null;
lock (Lock)
{
if (FireTime != null && FireTime.Value <= DateTime.Now)
{
a = Action;
FireTime = null;
Action = null;
}
}
if (a != null)
{
a();
}
}
}
public static Task Delay(int msDelay)
{
var time = DateTime.Now.AddMilliseconds(msDelay);
var tcs = new TaskCompletionSource<bool>();
lock (Lock)
{
if (FireTime != null)
throw new Exception();
FireTime = time;
Action = () => tcs.SetResult(true);
}
return tcs.Task;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment