Skip to content

Commit e7d233f

Browse files
committed
perf(device:cache): Cancel any previous refresh and only run the latest refresh
1 parent 785399e commit e7d233f

File tree

2 files changed

+13
-9
lines changed

2 files changed

+13
-9
lines changed

SoundSwitch/Framework/Audio/Lister/CachedAudioDeviceLister.cs

+12-8
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public DeviceReadOnlyCollection<DeviceFullInfo> GetDevices(DataFlow type, Device
5757
private readonly DeviceState _state;
5858
private readonly ILogger _context;
5959
private uint _threadSafeRefreshing;
60-
private DateTime _lastRefresh = DateTime.UtcNow;
60+
private CancellationTokenSource _refreshCancellationTokenSource = new CancellationTokenSource();
6161

6262
public bool Refreshing
6363
{
@@ -90,20 +90,19 @@ private void DeviceChanged(object sender, DeviceChangedEventBase e)
9090

9191
public void Refresh(CancellationToken cancellationToken = default)
9292
{
93-
if (Refreshing)
93+
// Cancel the previous refresh operation, if any
94+
var previousCts = Interlocked.Exchange(ref _refreshCancellationTokenSource, CancellationTokenSource.CreateLinkedTokenSource(cancellationToken));
95+
if (previousCts != null)
9496
{
95-
_context.Warning("Can't refresh, already refreshing since {LastRefresh}", _lastRefresh);
96-
//We want to be sure we get the latest refresh, it's not because we are refreshing that we'll get the latest info
97-
JobScheduler.Instance.ScheduleJob(new DebounceRefreshJob(_state, this, _context));
98-
99-
return;
97+
previousCts.Cancel();
98+
previousCts.Dispose();
10099
}
100+
cancellationToken = _refreshCancellationTokenSource.Token;
101101

102102
var stopWatch = Stopwatch.StartNew();
103103
try
104104
{
105105
Refreshing = true;
106-
_lastRefresh = DateTime.UtcNow;
107106
var playbackDevices = new Dictionary<string, DeviceFullInfo>();
108107
var recordingDevices = new Dictionary<string, DeviceFullInfo>();
109108

@@ -164,6 +163,9 @@ public void Refresh(CancellationToken cancellationToken = default)
164163
catch (NullReferenceException e) when (!cancellationToken.IsCancellationRequested)
165164
{
166165
_context.Error(e, "Can't refresh the devices");
166+
} catch(NullReferenceException e) when (cancellationToken.IsCancellationRequested)
167+
{
168+
_context.Information(e, "Cancellation requested and enumerator is disposed, ignoring");
167169
}
168170
}
169171
finally
@@ -181,6 +183,8 @@ public void Dispose()
181183
{
182184
device.Dispose();
183185
}
186+
187+
_refreshCancellationTokenSource.Dispose();
184188
}
185189
}
186190
}

SoundSwitch/Framework/Audio/Lister/Job/DebounceRefreshJob.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,5 @@ public Task OnFailure(JobException exception)
4343
public IRetryAction FailRule { get; } = new NoRetry();
4444
public TimeSpan? MaxRuntime { get; } = TimeSpan.FromSeconds(3);
4545
public string Key { get; }
46-
public TimeSpan DebounceTime { get; } = TimeSpan.FromMilliseconds(175);
46+
public TimeSpan DebounceTime { get; } = TimeSpan.FromMilliseconds(200);
4747
}

0 commit comments

Comments
 (0)