示例#1
0
        /// <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}");
            }
        }