UnityTaskScheduler.cs 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. public class UnityTaskScheduler : TaskScheduler
  7. {
  8. public string Name { get; }
  9. public UnitySynchronizationContext Context { get; }
  10. private readonly LinkedList<Task> queue = new LinkedList<Task>();
  11. public UnityTaskScheduler(string name)
  12. {
  13. Name = name;
  14. Context = new UnitySynchronizationContext(name);
  15. }
  16. public void Activate()
  17. {
  18. SynchronizationContext.SetSynchronizationContext(Context);
  19. Context.Activate();
  20. ExecutePendingTasks();
  21. Context.ExecutePendingContinuations();
  22. }
  23. protected override IEnumerable<Task> GetScheduledTasks()
  24. {
  25. lock (queue)
  26. {
  27. return queue.ToArray();
  28. }
  29. }
  30. protected override void QueueTask(Task task)
  31. {
  32. lock (queue)
  33. {
  34. queue.AddLast(task);
  35. }
  36. }
  37. protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
  38. {
  39. if (Context != SynchronizationContext.Current)
  40. {
  41. return false;
  42. }
  43. if (taskWasPreviouslyQueued)
  44. {
  45. lock (queue)
  46. {
  47. queue.Remove(task);
  48. }
  49. }
  50. return TryExecuteTask(task);
  51. }
  52. private void ExecutePendingTasks()
  53. {
  54. while (true)
  55. {
  56. Task task;
  57. lock (queue)
  58. {
  59. if (queue.Count == 0)
  60. {
  61. break;
  62. }
  63. task = queue.First.Value;
  64. queue.RemoveFirst();
  65. }
  66. if (task != null)
  67. {
  68. var result = TryExecuteTask(task);
  69. if (result == false)
  70. {
  71. throw new InvalidOperationException();
  72. }
  73. }
  74. }
  75. }
  76. }