public void ScanLibrary(Guid userId, Guid?collectionId, bool clear, CancellationToken cancellationToken) { if (ScanInProgress) { return; } Task.Run(async() => { ScanProgress = new ScanProgress(); ScanInProgress = true; _metadataRepositoryCache.UseCache = false; try { var collections = await _settingsRepository.GetCollectionsAsync(cancellationToken).ConfigureAwait(false); var collectionCount = 0; var collectionsToScan = collections.Where(c => c.Enabled).ToList(); if (collectionId.HasValue) { collectionsToScan = collectionsToScan.Where(c => c.Id == collectionId).ToList(); } ScanProgress.TotalCollectionCount = collectionsToScan.Count; foreach (var collection in collectionsToScan) { collectionCount++; ScanProgress.CurrentCollection = collectionCount; ScanProgress.CurrentCollectionId = collection.Id; if (!Directory.Exists(collection.Path)) { throw new Exception(); } if (clear) { collection.DateModified = DateTime.MinValue; await _metadataRepository.InsertOrUpdateCollectionAsync(collection, cancellationToken).ConfigureAwait(false); } var files = Directory.GetFiles(collection.Path, collection.Filter, SearchOption.AllDirectories); var fileCount = 0; ScanProgress.TotalFileCount = files.Length; foreach (var file in files) { fileCount++; ScanProgress.CurrentFile = fileCount; ScanProgress.CurrentFilename = file; if (fileCount == 1 || fileCount % 250 == 0) { _metadataRepository.EndTransaction(true, cancellationToken); _metadataRepository.BeginTransaction(cancellationToken); } await _metadataRepositoryCache.GetTrackAsync(userId, file, collection.Id, false, true, cancellationToken).ConfigureAwait(false); if (!ScanInProgress) { break; } } if (!ScanInProgress) { break; } _metadataRepository.EndTransaction(true, cancellationToken); foreach (var track in await _metadataRepository.GetTracksAsync(userId, collection.Id, cancellationToken).ConfigureAwait(false)) { var fileExists = File.Exists(track.Media.Path); if (track.Media.Visible == fileExists) { continue; } track.Media.Visible = fileExists; await _metadataRepository.InsertOrUpdateFileInfoAsync(track.Media, cancellationToken).ConfigureAwait(false); if (!fileExists) { await _metadataRepository.DeleteTrackReferencesAsync(track.Media, cancellationToken).ConfigureAwait(false); } } await _metadataRepository.DeleteAlbumReferencesAsync(cancellationToken).ConfigureAwait(false); } } catch (Exception ex) { _metadataRepository.EndTransaction(false, cancellationToken); File.WriteAllText($"{Guid.NewGuid():n}.txt", ex.ToString()); } finally { ScanProgress = null; ScanInProgress = false; _metadataRepositoryCache.UseCache = true; } }, cancellationToken); }