Skip to content

Commit dcf7e9d

Browse files
authored
Fix: Fixed crash that would sometimes occur when calculating folder sizes (#11012)
1 parent 7cd9e84 commit dcf7e9d

File tree

1 file changed

+16
-20
lines changed

1 file changed

+16
-20
lines changed

src/Files.Backend/Services/SizeProvider/DrivesSizeProvider.cs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using System;
2-
using System.Collections.Generic;
2+
using System.Collections.Concurrent;
33
using System.IO;
44
using System.Linq;
55
using System.Threading;
@@ -9,7 +9,7 @@ namespace Files.Backend.Services.SizeProvider
99
{
1010
public class DrivesSizeProvider : ISizeProvider
1111
{
12-
private readonly IDictionary<string, ISizeProvider> providers = new Dictionary<string, ISizeProvider>();
12+
private readonly ConcurrentDictionary<string, ISizeProvider> providers = new();
1313

1414
public event EventHandler<SizeChangedEventArgs>? SizeChanged;
1515

@@ -19,35 +19,31 @@ public async Task CleanAsync()
1919
var oldDriveNames = providers.Keys.Except(currentDrives).ToArray();
2020

2121
foreach (var oldDriveName in oldDriveNames)
22-
{
23-
if (providers.ContainsKey(oldDriveName))
24-
{
25-
providers.Remove(oldDriveName);
26-
}
27-
}
22+
providers.TryRemove(oldDriveName, out _);
23+
2824
foreach (var provider in providers.Values)
29-
{
3025
await provider.CleanAsync();
31-
}
3226
}
3327

3428
public async Task ClearAsync()
3529
{
36-
foreach (var provider in providers)
37-
{
38-
await provider.Value.ClearAsync();
39-
}
30+
foreach (var provider in providers.Values)
31+
await provider.ClearAsync();
32+
4033
providers.Clear();
4134
}
4235

36+
/// <summary>
37+
/// Delegate the update to an instance of CachedSizeProvider.
38+
/// This method is reentrant (thread safe) to avoid having to await each result.
39+
/// </summary>
4340
public Task UpdateAsync(string path, CancellationToken cancellationToken)
4441
{
4542
string driveName = GetDriveName(path);
46-
if (!providers.ContainsKey(driveName))
43+
var provider = providers.GetOrAdd(driveName, (key) =>
4744
{
48-
CreateProvider(driveName);
49-
}
50-
var provider = providers[driveName];
45+
return CreateProvider();
46+
});
5147
return provider.UpdateAsync(path, cancellationToken);
5248
}
5349

@@ -65,11 +61,11 @@ public bool TryGetSize(string path, out ulong size)
6561

6662
private static string GetDriveName(string path) => Directory.GetDirectoryRoot(path);
6763

68-
private void CreateProvider(string driveName)
64+
private ISizeProvider CreateProvider()
6965
{
7066
var provider = new CachedSizeProvider();
7167
provider.SizeChanged += Provider_SizeChanged;
72-
providers.Add(driveName, provider);
68+
return provider;
7369
}
7470

7571
private void Provider_SizeChanged(object? sender, SizeChangedEventArgs e)

0 commit comments

Comments
 (0)