protected override async Task ProcessAsync(Job job, CancellationToken token) { await base.ProcessAsync(job, token); // (targetEachVerses, mainBook, mainChapter) var queue = new ConcurrentQueue <Tuple <IEnumerable <IEnumerable <Verse> >, Book, Chapter> >(); var sync = new AutoResetEvent(false); var queries = job.QueryString.Split().Select(VerseQuery.Parse).ToList(); var e = new JobProgressEventArgs(job, null, 0, queries.Count, 0, 0); OnJobProgress(e); var produce = Task.Run(async() => { var eachBooks = await GetEachBooksAsync(job.Bibles, token); foreach (var query in queries) { var targetEachBook = eachBooks.Select(books => books.FirstOrDefault(book => book.Abbreviation == query.BookAbbreviation)).ToList(); // 해당 책이 있는 성경에서 해당 책을 대표로 사용 var mainBook = targetEachBook.FirstOrDefault(i => i != null); if (mainBook == null) { goto PROGRESS_QUERY; } var eachTargetChapters = (await GetEachChaptersAsync(targetEachBook, token)) .Select(chapters => chapters .Where(chapter => (query.EndChapterNumber == null) ? (chapter.Number >= query.StartChapterNumber) : (chapter.Number >= query.StartChapterNumber) && (chapter.Number <= query.EndChapterNumber)) .ToList()) .ToList(); // 장 번호를 기준으로 각 성경의 책을 순회하도록 관리 var targetEachChapters = Inverse(eachTargetChapters); e = new JobProgressEventArgs(job, e.CurrentChapter, e.QueriesDone, e.Queries, e.ChaptersDone, e.Chapters + targetEachChapters.Count()); foreach (var targetEachChapter in targetEachChapters) { // 해당 장이 있는 성경의 책에서 해당 장을 대표로 사용 var mainChapter = targetEachChapter.FirstOrDefault(i => i != null); if (mainChapter == null) { goto PROGRESS_CHAPTER; } e = new JobProgressEventArgs(job, mainChapter, e.QueriesDone, e.Queries, e.ChaptersDone, e.Chapters); var startVerseNumber = (mainChapter.Number == query.StartChapterNumber) ? query.StartVerseNumber : 1; var endVerseNumber = (mainChapter.Number == query.EndChapterNumber) ? query.EndVerseNumber : null; var eachTargetVerses = (await GetEachVersesAsync(targetEachChapter, token)) .Select(verses => verses .Where(verse => (endVerseNumber == null) ? (verse.Number >= startVerseNumber) : (verse.Number >= startVerseNumber) && (verse.Number <= endVerseNumber)) .ToList()) .ToList(); var targetEachVerses = Inverse(eachTargetVerses); queue.Enqueue(Tuple.Create(targetEachVerses, mainBook, mainChapter)); sync.WaitOne(); PROGRESS_CHAPTER: e = new JobProgressEventArgs(job, e.CurrentChapter, e.QueriesDone, e.Queries, e.ChaptersDone + 1, e.Chapters); } PROGRESS_QUERY: e = new JobProgressEventArgs(job, e.CurrentChapter, e.QueriesDone + 1, e.Queries, e.ChaptersDone, e.Chapters); } }); var chaptersDone = 0; if (job.SplitChaptersIntoFiles) { while (queue.Any() || !(produce.IsCompleted || (produce.Status == TaskStatus.RanToCompletion))) { if (queue.TryDequeue(out var item)) { sync.Set(); var targetEachVerses = item.Item1; var mainBook = item.Item2; var mainChapter = item.Item3; var output = Path.Combine(job.OutputDestination, mainBook.Name, mainChapter.Number.ToString(@"000\.pptx")); CreateDirectoryIfNotExists(Path.GetDirectoryName(output)); using (var ppt = new PPTManager(POWERPNT, job, output)) { ppt.AppendChapter(targetEachVerses, mainBook, mainChapter, token); ppt.Save(); } OnJobProgress(new JobProgressEventArgs(job, null, e.QueriesDone, e.Queries, ++chaptersDone, e.Chapters)); } } } else { using (var ppt = new PPTManager(POWERPNT, job, job.OutputDestination)) { while (queue.Any() || !(produce.IsCompleted || (produce.Status == TaskStatus.RanToCompletion))) { if (queue.TryDequeue(out var item)) { sync.Set(); var targetEachVerses = item.Item1; var mainBook = item.Item2; var mainChapter = item.Item3; ppt.AppendChapter(targetEachVerses, mainBook, mainChapter, token); OnJobProgress(new JobProgressEventArgs(job, null, e.QueriesDone, e.Queries, ++chaptersDone, e.Chapters)); } } ppt.Save(); } } await produce; }
protected virtual void OnJobProgress(JobProgressEventArgs e) => JobProgress?.Report(e);
protected virtual void OnJobProgress(JobProgressEventArgs e) => JobProgress?.Invoke(this, e);