AsyncGroup.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. using System;
  2. using System.Collections.Generic;
  3. namespace XGame.Framework.Asyncs
  4. {
  5. public class AsyncGroup<TAwaiter> : AsyncAwaitable<TAwaiter>, IAsyncGroup, IDisposable, IAsyncListener where TAwaiter : IAwaiter, new()
  6. {
  7. protected HashSet<IAsync> elements;
  8. /// <summary>
  9. /// 是否不包含任务子异步,一般地如果为空则异步组就没什么价值
  10. /// </summary>
  11. public bool Empty { get; private set; } = true;
  12. private bool bEnded = false;
  13. /// <summary>
  14. /// 执行中的任务子异步数量,用于计算Progress
  15. /// </summary>
  16. private int asyncCount = 0;
  17. public override float Progress
  18. {
  19. get
  20. {
  21. if (IsCompleted || elements == null || asyncCount <= 0)
  22. return base.Progress;
  23. float progress = 0;
  24. int count = elements.Count;
  25. foreach (var it in elements)
  26. {
  27. progress += it.Progress;
  28. }
  29. if (asyncCount >= count)
  30. {
  31. return (progress + asyncCount - count) / asyncCount;
  32. }
  33. return progress / count;
  34. }
  35. protected set => base.Progress = value;
  36. }
  37. public void AddAsync(IAsync ele)
  38. {
  39. if (ele == null || ele.IsCompleted)
  40. return;
  41. Empty = false;
  42. if (elements == null)
  43. {
  44. elements = new HashSet<IAsync>();
  45. }
  46. if (elements.Add(ele))
  47. {
  48. ele.On(this, 100);
  49. asyncCount++;
  50. }
  51. }
  52. public void RemoveAsync(IAsync ele)
  53. {
  54. if (elements == null) return;
  55. if (elements.Remove(ele))
  56. {
  57. ele.RemoveOn(this);
  58. asyncCount--;
  59. }
  60. }
  61. public void OnAsyncCompleted(IAsync aAsync)
  62. {
  63. if (aAsync.Exception != null)
  64. {
  65. if (Exception == null)
  66. {
  67. Exception = new AsyncGroupException();
  68. }
  69. (Exception as AsyncGroupException).AddException(aAsync.Exception);
  70. }
  71. elements?.Remove(aAsync);
  72. Check();
  73. }
  74. /// <summary>
  75. /// 避免在添加过程中出现异步已经完成的情况!
  76. /// 需要确定一个时机表示AsyncGroup已经添加完子元素
  77. /// </summary>
  78. public void End()
  79. {
  80. if (bEnded) return;
  81. bEnded = true;
  82. Check();
  83. }
  84. private void Check()
  85. {
  86. if (!bEnded) return;
  87. if (elements == null || elements.Count == 0)
  88. {
  89. asyncCount = 0;
  90. Completed();
  91. }
  92. }
  93. protected override void OnRemoveAll()
  94. {
  95. if (elements != null)
  96. {
  97. foreach (var element in elements)
  98. {
  99. element?.RemoveAll();
  100. }
  101. elements.Clear();
  102. }
  103. }
  104. public void Dispose()
  105. {
  106. if (Empty && !IsCompleted)
  107. {
  108. Completed();
  109. }
  110. }
  111. }
  112. public class AsyncGroup : AsyncGroup<Awaiter> { }
  113. }