/// <summary> /// 非同期で画像を読み込む /// </summary> /// <param name="folderPath"></param> /// <returns></returns> public async Task LoadVRCPhotoListAsync(string[] folderPaths, CancellationToken cancelToken) { _db.CreateDBCacheIfNeeded(); if (folderPaths.Any(f => !Directory.Exists(f))) { throw new DirectoryNotFoundException($"{string.Join(',',folderPaths.Where(f => !Directory.Exists(f)))} is not exist."); } Collection.Clear(); try { // UIスレッドと分離させる await Task.Run(async() => { var filePaths = folderPaths.SelectMany(f => Directory.GetFiles(f, "*.png", SearchOption.TopDirectoryOnly)) .Where(x => !x.StartsWith(AppCache.Instance.CacheFolderPath, StringComparison.Ordinal)) .ToList(); var metaSets = _db.GetVrcMetaDataIfExists(filePaths); var photos = metaSets .Select(m => new Photo(m.filePath) { MetaData = m.vrcMetaData }) .ToList(); Collection.AddRangeOnScheduler(photos); var tasks = filePaths .Except(metaSets.Select(m => m.filePath)) .Select(fp => new Task(async() => { var meta = await MetaDataHelper.GetVrcMetaDataAsync(fp, cancelToken).ConfigureAwait(true); if (cancelToken.IsCancellationRequested) { return; } Collection.AddOnScheduler( new Photo(fp) { MetaData = meta }); try { await _db.InsertAsync(fp, meta, cancelToken).ConfigureAwait(false); } catch (InvalidOperationException e) { // A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913. // The instance of entity type 'Photo' cannot be tracked because another instance with the same key value for {'FilePath'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values. FileHelper.OutputErrorLogFile(e); } catch (ArgumentException e) { FileHelper.OutputErrorLogFile(e); } catch (Microsoft.EntityFrameworkCore.DbUpdateException e) { // An error occurred while updating the entries. See the inner exception for details. FileHelper.OutputErrorLogFile(e); } catch (TaskCanceledException e) { } }, cancelToken)); Debug.Print($"{tasks.Count()}/{filePaths.Count}"); foreach (var task in tasks) { if (cancelToken.IsCancellationRequested) { return; } task.Start(); } }, cancelToken).ConfigureAwait(true); _db.SaveChanges(); } catch (Exception e) { Debug.Print($"{e.GetType().Name}: {e.Message}"); } }