diff --git a/src/Dragon-ISO.Engine/Discovery/NdiDiscoveryService.cs b/src/Dragon-ISO.Engine/Discovery/NdiDiscoveryService.cs
index 4a0e4a2..f8b7e58 100644
--- a/src/Dragon-ISO.Engine/Discovery/NdiDiscoveryService.cs
+++ b/src/Dragon-ISO.Engine/Discovery/NdiDiscoveryService.cs
@@ -187,23 +187,42 @@ public sealed class NdiDiscoveryService
}
///
- /// Dispose the current finder and create a fresh one against the cached
- /// discovery groups. Clears the seen-set so all currently-visible sources
- /// will re-fire as on the next poll.
+ /// Create a fresh finder against the cached discovery groups and, only once it
+ /// is successfully in hand, dispose the old one and clear the seen-set so all
+ /// currently-visible sources re-fire as on
+ /// the next poll.
+ ///
+ /// Ordering matters: we build the replacement before disposing the
+ /// incumbent. If throws (the failure mode
+ /// this method's catch exists for), the incumbent finder is left untouched and
+ /// fully usable, the seen-set is preserved (no spurious re-Add storm), and the
+ /// loop simply keeps polling the existing finder until the next rebuild attempt.
+ ///
+ /// Returns true if the finder was actually swapped; false if the rebuild failed
+ /// and the existing finder was retained. Internal for unit-testing the failure
+ /// path.
///
- private void RebuildFinder(string reason)
+ internal bool RebuildFinder(string reason)
{
+ NdiFindHandle replacement;
try
{
_logger.LogInformation("Rebuilding NDI finder ({Reason}).", reason);
- _finder.Dispose();
- _finder = _interop.CreateFinder(_discoveryGroups);
- _previous.Clear();
+ replacement = _interop.CreateFinder(_discoveryGroups);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Finder rebuild failed ({Reason}); continuing with existing finder.", reason);
+ return false;
}
+
+ // New finder is live — retire the old one and reset discovery state.
+ var old = _finder;
+ _finder = replacement;
+ try { old.Dispose(); }
+ catch (Exception ex) { _logger.LogWarning(ex, "Disposing previous finder threw after rebuild ({Reason}).", reason); }
+ _previous.Clear();
+ return true;
}
///