// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace EpicGames.Core { /// /// Utility functions for manipulating async tasks /// public static class AsyncUtils { /// /// Converts a cancellation token to a waitable task /// /// Cancellation token /// public static Task AsTask(this CancellationToken token) { return Task.Delay(-1, token).ContinueWith(x => { }); } /// /// Converts a cancellation token to a waitable task /// /// Cancellation token /// public static Task AsTask(this CancellationToken token) { return Task.Delay(-1, token).ContinueWith(_ => Task.FromCanceled(token)).Unwrap(); } /// /// Attempts to get the result of a task, if it has finished /// /// /// /// /// public static bool TryGetResult(this Task task, out T result) { if (task.IsCompleted) { result = task.Result; return true; } else { result = default!; return false; } } /// /// Waits for a time period to elapse or the task to be cancelled, without throwing an cancellation exception /// /// Time to wait /// Cancellation token /// public static Task DelayNoThrow(TimeSpan time, CancellationToken token) { return Task.Delay(time, token).ContinueWith(x => { }); } /// /// Removes all the complete tasks from a list, allowing each to throw exceptions as necessary /// /// List of tasks to remove tasks from public static void RemoveCompleteTasks(this List tasks) { List exceptions = new List(); int outIdx = 0; for (int idx = 0; idx < tasks.Count; idx++) { if (tasks[idx].IsCompleted) { AggregateException? exception = tasks[idx].Exception; if (exception != null) { exceptions.AddRange(exception.InnerExceptions); } } else { if (idx != outIdx) { tasks[outIdx] = tasks[idx]; } outIdx++; } } tasks.RemoveRange(outIdx, tasks.Count - outIdx); if (exceptions.Count > 0) { throw new AggregateException(exceptions); } } /// /// Removes all the complete tasks from a list, allowing each to throw exceptions as necessary /// /// List of tasks to remove tasks from /// Return values from the completed tasks public static List RemoveCompleteTasks(this List> tasks) { List results = new List(); int outIdx = 0; for (int idx = 0; idx < tasks.Count; idx++) { if (tasks[idx].IsCompleted) { results.Add(tasks[idx].Result); } else if (idx != outIdx) { tasks[outIdx++] = tasks[idx]; } } tasks.RemoveRange(outIdx, tasks.Count - outIdx); return results; } } }