diff --git a/LightlessSync/Services/LightFinder/LightFinderScannerService.cs b/LightlessSync/Services/LightFinder/LightFinderScannerService.cs index 52ff1dc..35c7d0b 100644 --- a/LightlessSync/Services/LightFinder/LightFinderScannerService.cs +++ b/LightlessSync/Services/LightFinder/LightFinderScannerService.cs @@ -1,4 +1,4 @@ -using Dalamud.Plugin.Services; +using Dalamud.Plugin.Services; using LightlessSync.API.Dto.User; using LightlessSync.Services.ActorTracking; using LightlessSync.Services.Mediator; @@ -33,6 +33,7 @@ public class LightFinderScannerService : DisposableMediatorSubscriberBase private const int _maxQueueSize = 100; private volatile bool _batchRunning = false; + private volatile bool _disposed = false; public IReadOnlyDictionary BroadcastCache => _broadcastCache; public readonly record struct BroadcastEntry(bool IsBroadcasting, DateTime ExpiryTime, string? GID); @@ -63,6 +64,9 @@ public class LightFinderScannerService : DisposableMediatorSubscriberBase public void Update() { + if (_disposed) + return; + _frameCounter++; var lookupsThisFrame = 0; @@ -104,7 +108,14 @@ public class LightFinderScannerService : DisposableMediatorSubscriberBase private async Task BatchUpdateBroadcastCacheAsync(List cids) { + if (_disposed) + return; + var results = await _broadcastService.AreUsersBroadcastingAsync(cids).ConfigureAwait(false); + + if (_disposed) + return; + var now = DateTime.UtcNow; foreach (var (cid, info) in results) @@ -123,6 +134,9 @@ public class LightFinderScannerService : DisposableMediatorSubscriberBase (_, old) => new BroadcastEntry(info.IsBroadcasting, expiry, info.GID)); } + if (_disposed) + return; + var activeCids = _broadcastCache .Where(e => e.Value.IsBroadcasting && e.Value.ExpiryTime > now) .Select(e => e.Key) @@ -134,6 +148,9 @@ public class LightFinderScannerService : DisposableMediatorSubscriberBase private void OnBroadcastStatusChanged(BroadcastStatusChangedMessage msg) { + if (_disposed) + return; + if (!msg.Enabled) { _broadcastCache.Clear(); @@ -147,6 +164,9 @@ public class LightFinderScannerService : DisposableMediatorSubscriberBase private void UpdateSyncshellBroadcasts() { + if (_disposed) + return; + var now = DateTime.UtcNow; var newSet = _broadcastCache .Where(e => e.Value.IsBroadcasting && e.Value.ExpiryTime > now && !string.IsNullOrEmpty(e.Value.GID)) @@ -230,17 +250,35 @@ public class LightFinderScannerService : DisposableMediatorSubscriberBase protected override void Dispose(bool disposing) { + _disposed = true; base.Dispose(disposing); _framework.Update -= OnFrameworkUpdate; - if (_cleanupTask != null) + + try { - _cleanupTask?.Wait(100, _cleanupCts.Token); + _cleanupCts.Cancel(); + } + catch (ObjectDisposedException) + { + // Already disposed, can be ignored :) } - _cleanupCts.Cancel(); - _cleanupCts.Dispose(); + try + { + _cleanupTask?.Wait(100); + } + catch (Exception) + { + // Task may have already completed or been cancelled? + } - _cleanupTask?.Wait(100); - _cleanupCts.Dispose(); + try + { + _cleanupCts.Dispose(); + } + catch (ObjectDisposedException) + { + // Already disposed, ignore + } } }