@@ -19,6 +19,7 @@ public sealed class EverythingSizeProvider : ISizeProvider
1919 private readonly IEverythingSearchService everythingService ;
2020 private readonly IGeneralSettingsService generalSettings ;
2121 private static EverythingSdk3Service _sdk3Service ;
22+ private readonly SemaphoreSlim _calculationSemaphore = new ( 3 ) ; // Limit concurrent calculations
2223
2324 public event EventHandler < SizeChangedEventArgs > ? SizeChanged ;
2425
@@ -77,45 +78,55 @@ public Task ClearAsync()
7778
7879 public async Task UpdateAsync ( string path , CancellationToken cancellationToken )
7980 {
80- await Task . Yield ( ) ;
81-
82-
8381 // Return cached size immediately if available
8482 if ( sizes . TryGetValue ( path , out ulong cachedSize ) )
8583 {
8684 RaiseSizeChanged ( path , cachedSize , SizeChangedValueState . Final ) ;
87- }
88- else
89- {
90- RaiseSizeChanged ( path , 0 , SizeChangedValueState . None ) ;
91- }
92-
93- // Check if Everything is available
94- if ( ! everythingService . IsEverythingAvailable ( ) )
95- {
96- await FallbackCalculateAsync ( path , cancellationToken ) ;
9785 return ;
9886 }
9987
100- try
88+ // Indicate that calculation is starting
89+ RaiseSizeChanged ( path , 0 , SizeChangedValueState . None ) ;
90+
91+ // Run the entire calculation on a background thread to avoid blocking
92+ await Task . Run ( async ( ) =>
10193 {
102- // Calculate using Everything
103- ulong totalSize = await CalculateWithEverythingAsync ( path , cancellationToken ) ;
104-
105- if ( totalSize == 0 )
94+ // Limit concurrent calculations
95+ await _calculationSemaphore . WaitAsync ( cancellationToken ) ;
96+ try
10697 {
107- // Everything returned 0, use fallback
108- await FallbackCalculateAsync ( path , cancellationToken ) ;
109- return ;
98+ // Check if Everything is available
99+ if ( ! everythingService . IsEverythingAvailable ( ) )
100+ {
101+ await FallbackCalculateAsync ( path , cancellationToken ) ;
102+ return ;
103+ }
104+
105+ try
106+ {
107+ // Calculate using Everything
108+ ulong totalSize = await CalculateWithEverythingAsync ( path , cancellationToken ) ;
109+
110+ if ( totalSize == 0 )
111+ {
112+ // Everything returned 0, use fallback
113+ await FallbackCalculateAsync ( path , cancellationToken ) ;
114+ return ;
115+ }
116+ sizes [ path ] = totalSize ;
117+ RaiseSizeChanged ( path , totalSize , SizeChangedValueState . Final ) ;
118+ }
119+ catch ( Exception ex )
120+ {
121+ // Fall back to standard calculation on error
122+ await FallbackCalculateAsync ( path , cancellationToken ) ;
123+ }
110124 }
111- sizes [ path ] = totalSize ;
112- RaiseSizeChanged ( path , totalSize , SizeChangedValueState . Final ) ;
113- }
114- catch ( Exception ex )
115- {
116- // Fall back to standard calculation on error
117- await FallbackCalculateAsync ( path , cancellationToken ) ;
118- }
125+ finally
126+ {
127+ _calculationSemaphore . Release ( ) ;
128+ }
129+ } , cancellationToken ) . ConfigureAwait ( false ) ;
119130 }
120131
121132 private async Task < ulong > CalculateWithEverythingAsync ( string path , CancellationToken cancellationToken )
@@ -147,13 +158,21 @@ private async Task<ulong> CalculateWithEverythingAsync(string path, Cancellation
147158 {
148159 try
149160 {
150- var size = await Task . Run ( ( ) => _sdk3Service . GetFolderSize ( path ) , cancellationToken ) ;
161+ // Use a timeout for SDK3 queries to prevent hanging
162+ using var cts = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
163+ cts . CancelAfter ( TimeSpan . FromSeconds ( 2 ) ) ; // 2 second timeout
164+
165+ var size = await Task . Run ( ( ) => _sdk3Service . GetFolderSize ( path ) , cts . Token ) ;
151166 if ( size > 0 )
152167 {
153168 App . Logger ? . LogInformation ( $ "[EverythingSizeProvider SDK3] Got folder size for { path } : { size } bytes") ;
154169 return size ;
155170 }
156171 }
172+ catch ( OperationCanceledException )
173+ {
174+ App . Logger ? . LogWarning ( $ "[EverythingSizeProvider SDK3] Timeout getting folder size for { path } ") ;
175+ }
157176 catch ( Exception ex )
158177 {
159178 App . Logger ? . LogError ( ex , $ "[EverythingSizeProvider SDK3] Error getting folder size for { path } ") ;
@@ -326,7 +345,11 @@ async Task<ulong> CalculateRecursive(string currentPath, CancellationToken ct, i
326345
327346 public bool TryGetSize ( string path , out ulong size ) => sizes . TryGetValue ( path , out size ) ;
328347
329- public void Dispose ( ) { }
348+ public void Dispose ( )
349+ {
350+ _calculationSemaphore ? . Dispose ( ) ;
351+ _sdk3Service ? . Dispose ( ) ;
352+ }
330353
331354 private void RaiseSizeChanged ( string path , ulong newSize , SizeChangedValueState valueState )
332355 => SizeChanged ? . Invoke ( this , new SizeChangedEventArgs ( path , newSize , valueState ) ) ;
0 commit comments