diff --git a/src/Speckle.Sdk/Serialisation/V2/Send/PriorityScheduler.cs b/src/Speckle.Sdk/Serialisation/V2/Send/PriorityScheduler.cs
index 3e254d1e..c38a3df3 100644
--- a/src/Speckle.Sdk/Serialisation/V2/Send/PriorityScheduler.cs
+++ b/src/Speckle.Sdk/Serialisation/V2/Send/PriorityScheduler.cs
@@ -4,10 +4,17 @@ namespace Speckle.Sdk.Serialisation.V2.Send;
 
 public sealed class PriorityScheduler(ThreadPriority priority, int maximumConcurrencyLevel) : TaskScheduler, IDisposable
 {
+  private readonly CancellationTokenSource _cancellationTokenSource = new();
   private readonly BlockingCollection<Task> _tasks = new();
   private Thread[]? _threads;
 
-  public void Dispose() => _tasks.Dispose();
+  public void Dispose()
+  {
+    _tasks.CompleteAdding();
+    _cancellationTokenSource.Cancel();
+    _tasks.Dispose();
+    _cancellationTokenSource.Dispose();
+  }
 
   public override int MaximumConcurrencyLevel => maximumConcurrencyLevel;
 
@@ -24,9 +31,26 @@ protected override void QueueTask(Task task)
       {
         _threads[i] = new Thread(() =>
         {
-          foreach (Task t in _tasks.GetConsumingEnumerable())
+          try
+          {
+            foreach (Task t in _tasks.GetConsumingEnumerable(_cancellationTokenSource.Token))
+            {
+              if (_cancellationTokenSource.IsCancellationRequested)
+              {
+                break;
+              }
+              TryExecuteTask(t);
+              if (_cancellationTokenSource.IsCancellationRequested)
+              {
+                break;
+              }
+            }
+          }
+#pragma warning disable CA1031
+          catch (Exception)
+#pragma warning restore CA1031
           {
-            TryExecuteTask(t);
+            // ignored
           }
         })
         {