diff --git a/src/Tgstation.Server.Common/Extensions/ValueTaskExtensions.cs b/src/Tgstation.Server.Common/Extensions/ValueTaskExtensions.cs
new file mode 100644
index 0000000000..884b30379a
--- /dev/null
+++ b/src/Tgstation.Server.Common/Extensions/ValueTaskExtensions.cs
@@ -0,0 +1,169 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading.Tasks;
+
+namespace Tgstation.Server.Common.Extensions
+{
+ ///
+ /// Extension methods for the and es.
+ ///
+ public static class ValueTaskExtensions
+ {
+ ///
+ /// Fully a given list of .
+ ///
+ /// The type.
+ /// An of s.
+ /// The number of elements in .
+ /// A representing the combined .
+ /// An containing any s thrown by the .
+ public static async ValueTask WhenAll(IEnumerable> tasks, int totalTasks)
+ {
+ if (tasks == null)
+ throw new ArgumentNullException(nameof(tasks));
+
+ // We don't allocate the list if no task throws
+ List? exceptions = null;
+ int i = 0;
+ var results = new T[totalTasks];
+ foreach (var task in tasks)
+ {
+ try
+ {
+ results[i] = await task.ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ exceptions ??= new (totalTasks - i);
+ exceptions.Add(ex);
+ }
+
+ ++i;
+ }
+
+ Debug.Assert(totalTasks == i, "Invalid count specified!");
+
+ if (exceptions != null)
+ throw new AggregateException(exceptions);
+
+ return results;
+ }
+
+ ///
+ /// Fully a given list of .
+ ///
+ /// The type.
+ /// An of s.
+ /// A containing the of results based on .
+ /// An containing any s thrown by the .
+ public static async ValueTask WhenAll(IReadOnlyList> tasks)
+ {
+ if (tasks == null)
+ throw new ArgumentNullException(nameof(tasks));
+
+ var totalTasks = tasks.Count;
+ if (totalTasks == 0)
+ return Array.Empty();
+
+ // We don't allocate the list if no task throws
+ List? exceptions = null;
+ var results = new T[totalTasks];
+ for (var i = 0; i < totalTasks; i++)
+ try
+ {
+ results[i] = await tasks[i].ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ exceptions ??= new (totalTasks - i);
+ exceptions.Add(ex);
+ }
+
+ return exceptions == null
+ ? results
+ : throw new AggregateException(exceptions);
+ }
+
+ ///
+ /// Fully a given list of .
+ ///
+ /// The type.
+ /// An of s.
+ /// A containing the of results based on .
+ /// An containing any s thrown by the .
+ public static ValueTask WhenAll(params ValueTask[] tasks) => WhenAll((IReadOnlyList>)tasks);
+
+ ///
+ /// Fully a given list of .
+ ///
+ /// An of s.
+ /// The number of elements in .
+ /// A representing the combined .
+ /// An containing any s thrown by the .
+ public static async ValueTask WhenAll(IEnumerable tasks, int totalTasks)
+ {
+ if (tasks == null)
+ throw new ArgumentNullException(nameof(tasks));
+
+ // We don't allocate the list if no task throws
+ List? exceptions = null;
+ int i = 0;
+ foreach (var task in tasks)
+ {
+ try
+ {
+ await task.ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ exceptions ??= new (totalTasks - i);
+ exceptions.Add(ex);
+ }
+
+ ++i;
+ }
+
+ Debug.Assert(totalTasks == i, "Invalid count specified!");
+
+ if (exceptions != null)
+ throw new AggregateException(exceptions);
+ }
+
+ ///
+ /// Fully a given list of .
+ ///
+ /// An of s.
+ /// A representing the combined .
+ /// An containing any s thrown by the .
+ public static async ValueTask WhenAll(IReadOnlyList tasks)
+ {
+ if (tasks == null)
+ throw new ArgumentNullException(nameof(tasks));
+
+ // We don't allocate the list if no task throws
+ List? exceptions = null;
+ foreach (var task in tasks)
+ try
+ {
+ await task.ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ exceptions ??= new ();
+ exceptions.Add(ex);
+ }
+
+ if (exceptions != null)
+ throw new AggregateException(exceptions);
+ }
+
+ ///
+ /// Fully a given list of .
+ ///
+ /// An of s.
+ /// A representing the combined .
+ /// An containing any s thrown by the .
+ public static ValueTask WhenAll(params ValueTask[] tasks) => WhenAll((IReadOnlyList)tasks);
+ }
+}
diff --git a/src/Tgstation.Server.Common/Tgstation.Server.Common.csproj b/src/Tgstation.Server.Common/Tgstation.Server.Common.csproj
index d7f263b375..802abe894a 100644
--- a/src/Tgstation.Server.Common/Tgstation.Server.Common.csproj
+++ b/src/Tgstation.Server.Common/Tgstation.Server.Common.csproj
@@ -23,6 +23,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
+