Improved BackgroundFileSystem thread safety
This commit is contained in:
parent
52fb0a27ce
commit
f74b0d78db
@ -34,7 +34,7 @@ namespace FileManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BackgroundFileSystem BookDirectoryFiles { get; } = new BackgroundFileSystem();
|
private static BackgroundFileSystem BookDirectoryFiles { get; set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region instance
|
#region instance
|
||||||
@ -47,6 +47,7 @@ namespace FileManager
|
|||||||
{
|
{
|
||||||
extensions_noDots = Extensions.Select(ext => ext.Trim('.')).ToList();
|
extensions_noDots = Extensions.Select(ext => ext.Trim('.')).ToList();
|
||||||
extAggr = extensions_noDots.Aggregate((a, b) => $"{a}|{b}");
|
extAggr = extensions_noDots.Aggregate((a, b) => $"{a}|{b}");
|
||||||
|
BookDirectoryFiles ??= new BackgroundFileSystem(BookDirectoryFiles, "*.*", SearchOption.AllDirectories);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Refresh()
|
public void Refresh()
|
||||||
@ -76,7 +77,15 @@ namespace FileManager
|
|||||||
{
|
{
|
||||||
//If user changed the BooksDirectory, reinitialize.
|
//If user changed the BooksDirectory, reinitialize.
|
||||||
if (storageDir != BookDirectoryFiles.RootDirectory)
|
if (storageDir != BookDirectoryFiles.RootDirectory)
|
||||||
BookDirectoryFiles.Init(storageDir, "*.*", SearchOption.AllDirectories);
|
{
|
||||||
|
lock (BookDirectoryFiles)
|
||||||
|
{
|
||||||
|
if (storageDir != BookDirectoryFiles.RootDirectory)
|
||||||
|
{
|
||||||
|
BookDirectoryFiles = new BackgroundFileSystem(storageDir, "*.*", SearchOption.AllDirectories);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
firstOrNull = BookDirectoryFiles.FindFile(regexPattern, RegexOptions.IgnoreCase);
|
firstOrNull = BookDirectoryFiles.FindFile(regexPattern, RegexOptions.IgnoreCase);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,12 +18,19 @@ namespace FileManager
|
|||||||
private FileSystemWatcher fileSystemWatcher { get; set; }
|
private FileSystemWatcher fileSystemWatcher { get; set; }
|
||||||
private BlockingCollection<FileSystemEventArgs> directoryChangesEvents { get; set; }
|
private BlockingCollection<FileSystemEventArgs> directoryChangesEvents { get; set; }
|
||||||
private Task backgroundScanner { get; set; }
|
private Task backgroundScanner { get; set; }
|
||||||
private List<string> fsCache { get; set; }
|
private List<string> fsCache { get; } = new();
|
||||||
|
|
||||||
|
public BackgroundFileSystem(string rootDirectory, string searchPattern, SearchOption searchOptions)
|
||||||
|
{
|
||||||
|
RootDirectory = rootDirectory;
|
||||||
|
SearchPattern = searchPattern;
|
||||||
|
SearchOption = searchOptions;
|
||||||
|
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
public string FindFile(string regexPattern, RegexOptions options)
|
public string FindFile(string regexPattern, RegexOptions options)
|
||||||
{
|
{
|
||||||
if (fsCache is null) return null;
|
|
||||||
|
|
||||||
lock (fsCache)
|
lock (fsCache)
|
||||||
{
|
{
|
||||||
return fsCache.FirstOrDefault(s => Regex.IsMatch(s, regexPattern, options));
|
return fsCache.FirstOrDefault(s => Regex.IsMatch(s, regexPattern, options));
|
||||||
@ -32,8 +39,6 @@ namespace FileManager
|
|||||||
|
|
||||||
public void RefreshFiles()
|
public void RefreshFiles()
|
||||||
{
|
{
|
||||||
if (fsCache is null) return;
|
|
||||||
|
|
||||||
lock (fsCache)
|
lock (fsCache)
|
||||||
{
|
{
|
||||||
fsCache.Clear();
|
fsCache.Clear();
|
||||||
@ -41,19 +46,12 @@ namespace FileManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init(string rootDirectory, string searchPattern, SearchOption searchOptions)
|
private void Init()
|
||||||
{
|
{
|
||||||
RootDirectory = rootDirectory;
|
Stop();
|
||||||
SearchPattern = searchPattern;
|
|
||||||
SearchOption = searchOptions;
|
|
||||||
|
|
||||||
//Calling CompleteAdding() will cause background scanner to terminate.
|
lock (fsCache)
|
||||||
directoryChangesEvents?.CompleteAdding();
|
fsCache.AddRange(Directory.EnumerateFiles(RootDirectory, SearchPattern, SearchOption));
|
||||||
fsCache?.Clear();
|
|
||||||
directoryChangesEvents?.Dispose();
|
|
||||||
fileSystemWatcher?.Dispose();
|
|
||||||
|
|
||||||
fsCache = Directory.EnumerateFiles(RootDirectory, SearchPattern, SearchOption).ToList();
|
|
||||||
|
|
||||||
directoryChangesEvents = new BlockingCollection<FileSystemEventArgs>();
|
directoryChangesEvents = new BlockingCollection<FileSystemEventArgs>();
|
||||||
fileSystemWatcher = new FileSystemWatcher(RootDirectory);
|
fileSystemWatcher = new FileSystemWatcher(RootDirectory);
|
||||||
@ -64,28 +62,31 @@ namespace FileManager
|
|||||||
fileSystemWatcher.IncludeSubdirectories = true;
|
fileSystemWatcher.IncludeSubdirectories = true;
|
||||||
fileSystemWatcher.EnableRaisingEvents = true;
|
fileSystemWatcher.EnableRaisingEvents = true;
|
||||||
|
|
||||||
//Wait for background scanner to terminate before reinitializing.
|
|
||||||
backgroundScanner?.Wait();
|
|
||||||
backgroundScanner = new Task(BackgroundScanner);
|
backgroundScanner = new Task(BackgroundScanner);
|
||||||
backgroundScanner.Start();
|
backgroundScanner.Start();
|
||||||
}
|
}
|
||||||
|
private void Stop()
|
||||||
|
{
|
||||||
|
//Stop raising events
|
||||||
|
fileSystemWatcher?.Dispose();
|
||||||
|
|
||||||
private void AddUniqueFiles(IEnumerable<string> newFiles)
|
//Calling CompleteAdding() will cause background scanner to terminate.
|
||||||
{
|
directoryChangesEvents?.CompleteAdding();
|
||||||
foreach (var file in newFiles)
|
|
||||||
{
|
//Wait for background scanner to terminate before reinitializing.
|
||||||
AddUniqueFile(file);
|
backgroundScanner?.Wait();
|
||||||
}
|
|
||||||
}
|
//Dispose of directoryChangesEvents after backgroundScanner exists.
|
||||||
private void AddUniqueFile(string newFile)
|
directoryChangesEvents?.Dispose();
|
||||||
{
|
|
||||||
if (!fsCache.Contains(newFile))
|
lock (fsCache)
|
||||||
fsCache.Add(newFile);
|
fsCache.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FileSystemWatcher_Error(object sender, ErrorEventArgs e)
|
private void FileSystemWatcher_Error(object sender, ErrorEventArgs e)
|
||||||
{
|
{
|
||||||
Init(RootDirectory, SearchPattern, SearchOption);
|
Stop();
|
||||||
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
|
private void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
|
||||||
@ -97,28 +98,26 @@ namespace FileManager
|
|||||||
private void BackgroundScanner()
|
private void BackgroundScanner()
|
||||||
{
|
{
|
||||||
while (directoryChangesEvents.TryTake(out FileSystemEventArgs change, -1))
|
while (directoryChangesEvents.TryTake(out FileSystemEventArgs change, -1))
|
||||||
UpdateLocalCache(change);
|
{
|
||||||
|
lock (fsCache)
|
||||||
|
UpdateLocalCache(change);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateLocalCache(FileSystemEventArgs change)
|
private void UpdateLocalCache(FileSystemEventArgs change)
|
||||||
{
|
{
|
||||||
lock (fsCache)
|
if (change.ChangeType == WatcherChangeTypes.Deleted)
|
||||||
{
|
{
|
||||||
if (change.ChangeType == WatcherChangeTypes.Deleted)
|
RemovePath(change.FullPath);
|
||||||
{
|
}
|
||||||
RemovePath(change.FullPath);
|
else if (change.ChangeType == WatcherChangeTypes.Created)
|
||||||
}
|
{
|
||||||
else if (change.ChangeType == WatcherChangeTypes.Created)
|
AddPath(change.FullPath);
|
||||||
{
|
}
|
||||||
AddPath(change.FullPath);
|
else if (change.ChangeType == WatcherChangeTypes.Renamed && change is RenamedEventArgs renameChange)
|
||||||
}
|
{
|
||||||
else if (change.ChangeType == WatcherChangeTypes.Renamed)
|
RemovePath(renameChange.OldFullPath);
|
||||||
{
|
AddPath(renameChange.FullPath);
|
||||||
var renameChange = change as RenamedEventArgs;
|
|
||||||
|
|
||||||
RemovePath(renameChange.OldFullPath);
|
|
||||||
AddPath(renameChange.FullPath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,6 +136,21 @@ namespace FileManager
|
|||||||
else
|
else
|
||||||
AddUniqueFile(path);
|
AddUniqueFile(path);
|
||||||
}
|
}
|
||||||
|
private void AddUniqueFiles(IEnumerable<string> newFiles)
|
||||||
|
{
|
||||||
|
foreach (var file in newFiles)
|
||||||
|
{
|
||||||
|
AddUniqueFile(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void AddUniqueFile(string newFile)
|
||||||
|
{
|
||||||
|
if (!fsCache.Contains(newFile))
|
||||||
|
fsCache.Add(newFile);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
~BackgroundFileSystem() => Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,8 +23,6 @@ namespace LibationWinForms
|
|||||||
if (DataGridView.Rows[RowIndex].DefaultCellStyle.ForeColor != foreColor)
|
if (DataGridView.Rows[RowIndex].DefaultCellStyle.ForeColor != foreColor)
|
||||||
{
|
{
|
||||||
DataGridView.Rows[RowIndex].DefaultCellStyle.ForeColor = foreColor;
|
DataGridView.Rows[RowIndex].DefaultCellStyle.ForeColor = foreColor;
|
||||||
|
|
||||||
DataGridView.InvalidateRow(RowIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tagsString.Length == 0)
|
if (tagsString.Length == 0)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user