fork(1) download
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6.  
  7. namespace TaskSchedulerBug
  8. {
  9. class Program
  10. {
  11. private static CustomTaskScheduler _scheduler;
  12. private static TaskFactory _factory;
  13.  
  14. static void Main(string[] args)
  15. {
  16. _scheduler = new CustomTaskScheduler();
  17. _factory = new TaskFactory(_scheduler);
  18.  
  19. var done = false;
  20.  
  21. _factory.StartNew(async () =>
  22. {
  23. await DoWork();
  24. done = true;
  25. });
  26.  
  27. while (!done)
  28. {
  29. _scheduler.Run();
  30. Thread.Sleep(1);
  31. }
  32. }
  33.  
  34. static async Task DoWork()
  35. {
  36. Console.WriteLine("Before await: {0}", TaskScheduler.Current);
  37.  
  38. var name = await GetName();
  39.  
  40. Console.WriteLine("After await: {0}", TaskScheduler.Current);
  41.  
  42. Console.WriteLine("hello {0}", name);
  43. }
  44.  
  45. static async Task<string> GetName()
  46. {
  47. return "Brian";
  48. }
  49. }
  50.  
  51. class CustomTaskScheduler : TaskScheduler
  52. {
  53. private ConcurrentQueue<Task> _tasks;
  54.  
  55. public CustomTaskScheduler()
  56. {
  57. _tasks = new ConcurrentQueue<Task>();
  58. }
  59.  
  60. public void Run()
  61. {
  62. var count = _tasks.Count;
  63.  
  64. if (count == 0)
  65. return;
  66.  
  67. while (--count >= 0)
  68. {
  69. Task task;
  70. if (!_tasks.TryDequeue(out task))
  71. break;
  72.  
  73. TryExecuteTask(task);
  74. }
  75. }
  76.  
  77. protected override IEnumerable<Task> GetScheduledTasks()
  78. {
  79. return _tasks;
  80. }
  81.  
  82. protected override void QueueTask(Task task)
  83. {
  84. _tasks.Enqueue(task);
  85. }
  86.  
  87. protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
  88. {
  89. if (taskWasPreviouslyQueued && !TryDequeue(task))
  90. return false;
  91.  
  92. return TryExecuteTask(task);
  93. }
  94. }
  95. }
  96.  
Success #stdin #stdout 0.05s 24360KB
stdin
Standard input is empty
stdout
Before await: TaskSchedulerBug.CustomTaskScheduler
After await: System.Threading.Tasks.TpScheduler
hello Brian