diff --git a/Runtime/TaskQueue/TaskQueue.cs b/Runtime/TaskQueue/TaskQueue.cs index 5ca0585..af6b3af 100644 --- a/Runtime/TaskQueue/TaskQueue.cs +++ b/Runtime/TaskQueue/TaskQueue.cs @@ -3,7 +3,6 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; using System.Threading; namespace Mew.Core.Tasks @@ -11,21 +10,33 @@ namespace Mew.Core.Tasks public class TaskQueue : IDisposable { private readonly List queue = new(); - private TaskAwaiter? awaiter; + private bool updateProcessing; + private bool taskProcessing; private CancellationTokenSource? cts; private CancellationToken? disposeCt; - protected string loopId = string.Empty; private object SyncRoot => ((ICollection)queue).SyncRoot; public TaskQueueLimitType LimitType { get; } + /// + /// Max size of queue. + /// public int MaxSize { get; } /// /// Count of running or waiting tasks. /// - public int Count => (queue?.Count ?? 0) + (awaiter.HasValue ? 1 : 0); + public int Count + { + get + { + lock (SyncRoot) + { + return queue.Count + (taskProcessing ? 1 : 0); + } + } + } /// /// true if started. @@ -168,7 +179,6 @@ private void CancelCurrent() cts?.Cancel(); cts?.Dispose(); cts = null; - awaiter = null; } private async void Update() @@ -179,25 +189,37 @@ private async void Update() return; } - if (awaiter.HasValue) return; + if (updateProcessing) return; + lock (SyncRoot) if (!queue.Any()) return; - TaskQueueAwaitable task; + updateProcessing = true; - lock (SyncRoot) + while (true) { - if (!queue.Any()) return; + using var taskCts = new CancellationTokenSource(); + TaskQueueAwaitable task; + + lock (SyncRoot) + { + task = queue.First(); + queue.RemoveAt(0); + taskProcessing = true; + } + + cts = disposeCt.HasValue + ? CancellationTokenSource.CreateLinkedTokenSource(taskCts.Token, disposeCt.Value) + : taskCts; + + await task.Invoke(cts.Token); + + cts?.Dispose(); + cts = null; - task = queue.First(); - queue.RemoveAt(0); + lock (SyncRoot) if (!queue.Any()) break; } - var taskCts = new CancellationTokenSource(); - cts = disposeCt.HasValue - ? CancellationTokenSource.CreateLinkedTokenSource(taskCts.Token, disposeCt.Value) - : taskCts; - var invokedTask = task.Invoke(cts.Token); - awaiter = invokedTask.GetAwaiter(); - await invokedTask.ContinueWith(_ => awaiter = null, taskCts.Token); + taskProcessing = false; + updateProcessing = false; } }