/// <summary> /// Queues a task-returning function to be executed /// in the queue processing. The returned result is /// another task that must be waited for. This new /// task is resolved when the function executes in /// its turn in the execution queue. /// </summary> /// <param name="task">The function to queue for execution</param> /// <returns>A task to be waited for, or null if either the task function is null or the current object is destroyed</returns> public Task Queue(Func <Task> task) { // Generate a new ID for debugging. ulong id = taskId++; XDebug debugger = new XDebug("Support", this, $"Queue(() => Task #{id})", debug); debugger.Start(); // Remember: It is FORBIDDEN to check for gameObject property. if (task == null || !this) { debugger.Info($"Returning a finished task for (null task?, this, gameObject) = ({task == null}, {this}, {gameObject})"); debugger.End(); return(Task.CompletedTask); } TaskCompletionSource <bool> source = new TaskCompletionSource <bool>(); debugger.Info($"Queuing task ${id}"); tasks.Enqueue(async() => { XDebug debugger2 = new XDebug("Support", this, $"Queue(() => Task #{id})::Body", debug); debugger2.Start(); try { await task(); source.SetResult(true); } catch (Exception e) { debugger2.Exception(e); source.SetException(e); } finally { debugger2.End(); } }); debugger.End(); return(source.Task); }