TaskTracker.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.Text;
  6. using System.Threading;
  7. using Cysharp.Threading.Tasks.Internal;
  8. namespace Cysharp.Threading.Tasks
  9. {
  10. // public for add user custom.
  11. public static class TaskTracker
  12. {
  13. #if UNITY_EDITOR
  14. static int trackingId = 0;
  15. public const string EnableAutoReloadKey = "UniTaskTrackerWindow_EnableAutoReloadKey";
  16. public const string EnableTrackingKey = "UniTaskTrackerWindow_EnableTrackingKey";
  17. public const string EnableStackTraceKey = "UniTaskTrackerWindow_EnableStackTraceKey";
  18. public static class EditorEnableState
  19. {
  20. static bool enableAutoReload;
  21. public static bool EnableAutoReload
  22. {
  23. get { return enableAutoReload; }
  24. set
  25. {
  26. enableAutoReload = value;
  27. UnityEditor.EditorPrefs.SetBool(EnableAutoReloadKey, value);
  28. }
  29. }
  30. static bool enableTracking;
  31. public static bool EnableTracking
  32. {
  33. get { return enableTracking; }
  34. set
  35. {
  36. enableTracking = value;
  37. UnityEditor.EditorPrefs.SetBool(EnableTrackingKey, value);
  38. }
  39. }
  40. static bool enableStackTrace;
  41. public static bool EnableStackTrace
  42. {
  43. get { return enableStackTrace; }
  44. set
  45. {
  46. enableStackTrace = value;
  47. UnityEditor.EditorPrefs.SetBool(EnableStackTraceKey, value);
  48. }
  49. }
  50. }
  51. #endif
  52. static List<KeyValuePair<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)>> listPool = new List<KeyValuePair<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)>>();
  53. static readonly WeakDictionary<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)> tracking = new WeakDictionary<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)>();
  54. [Conditional("UNITY_EDITOR")]
  55. public static void TrackActiveTask(IUniTaskSource task, int skipFrame)
  56. {
  57. #if UNITY_EDITOR
  58. dirty = true;
  59. if (!EditorEnableState.EnableTracking) return;
  60. var stackTrace = EditorEnableState.EnableStackTrace ? new StackTrace(skipFrame, true).CleanupAsyncStackTrace() : "";
  61. string typeName;
  62. if (EditorEnableState.EnableStackTrace)
  63. {
  64. var sb = new StringBuilder();
  65. TypeBeautify(task.GetType(), sb);
  66. typeName = sb.ToString();
  67. }
  68. else
  69. {
  70. typeName = task.GetType().Name;
  71. }
  72. tracking.TryAdd(task, (typeName, Interlocked.Increment(ref trackingId), DateTime.UtcNow, stackTrace));
  73. #endif
  74. }
  75. [Conditional("UNITY_EDITOR")]
  76. public static void RemoveTracking(IUniTaskSource task)
  77. {
  78. #if UNITY_EDITOR
  79. dirty = true;
  80. if (!EditorEnableState.EnableTracking) return;
  81. var success = tracking.TryRemove(task);
  82. #endif
  83. }
  84. static bool dirty;
  85. public static bool CheckAndResetDirty()
  86. {
  87. var current = dirty;
  88. dirty = false;
  89. return current;
  90. }
  91. /// <summary>(trackingId, awaiterType, awaiterStatus, createdTime, stackTrace)</summary>
  92. public static void ForEachActiveTask(Action<int, string, UniTaskStatus, DateTime, string> action)
  93. {
  94. lock (listPool)
  95. {
  96. var count = tracking.ToList(ref listPool, clear: false);
  97. try
  98. {
  99. for (int i = 0; i < count; i++)
  100. {
  101. action(listPool[i].Value.trackingId, listPool[i].Value.formattedType, listPool[i].Key.UnsafeGetStatus(), listPool[i].Value.addTime, listPool[i].Value.stackTrace);
  102. listPool[i] = default;
  103. }
  104. }
  105. catch
  106. {
  107. listPool.Clear();
  108. throw;
  109. }
  110. }
  111. }
  112. static void TypeBeautify(Type type, StringBuilder sb)
  113. {
  114. if (type.IsNested)
  115. {
  116. // TypeBeautify(type.DeclaringType, sb);
  117. sb.Append(type.DeclaringType.Name.ToString());
  118. sb.Append(".");
  119. }
  120. if (type.IsGenericType)
  121. {
  122. var genericsStart = type.Name.IndexOf("`");
  123. if (genericsStart != -1)
  124. {
  125. sb.Append(type.Name.Substring(0, genericsStart));
  126. }
  127. else
  128. {
  129. sb.Append(type.Name);
  130. }
  131. sb.Append("<");
  132. var first = true;
  133. foreach (var item in type.GetGenericArguments())
  134. {
  135. if (!first)
  136. {
  137. sb.Append(", ");
  138. }
  139. first = false;
  140. TypeBeautify(item, sb);
  141. }
  142. sb.Append(">");
  143. }
  144. else
  145. {
  146. sb.Append(type.Name);
  147. }
  148. }
  149. //static string RemoveUniTaskNamespace(string str)
  150. //{
  151. // return str.Replace("Cysharp.Threading.Tasks.CompilerServices", "")
  152. // .Replace("Cysharp.Threading.Tasks.Linq", "")
  153. // .Replace("Cysharp.Threading.Tasks", "");
  154. //}
  155. }
  156. }