public static List <BookScript> ParseBooks(IEnumerable <UsxDocument> books, IStylesheet stylesheet, Action <int> reportProgressAsPercent) { var numBlocksPerBook = new ConcurrentDictionary <string, int>(); var blocksInBook = new ConcurrentDictionary <string, XmlNodeList>(); Parallel.ForEach(books, usxDoc => { var nodeList = usxDoc.GetChaptersAndParas(); blocksInBook.AddOrUpdate(usxDoc.BookId, nodeList, (s, list) => nodeList); numBlocksPerBook.AddOrUpdate(usxDoc.BookId, nodeList.Count, (s, i) => nodeList.Count); }); int allBlocks = numBlocksPerBook.Values.Sum(); int completedBlocks = 0; var bookScripts = new List <BookScript>(blocksInBook.Count); Parallel.ForEach(blocksInBook, book => { var bookId = book.Key; var bookScript = new UsxParser(bookId, stylesheet, book.Value).CreateBookScript(); lock (bookScripts) bookScripts.Add(bookScript); Logger.WriteEvent("Added bookScript ({0}, {1})", bookId, bookScript.BookId); completedBlocks += numBlocksPerBook[bookId]; reportProgressAsPercent?.Invoke(MathUtilities.Percent(completedBlocks, allBlocks, 99)); }); // This code is an attempt to figure out how we are getting null reference exceptions on the Sort call (See PG-275 & PG-287) // The above call to lock bookScripts probably fixes the problem!!! :-) We hope... foreach (var bookScript in bookScripts) { if (bookScript?.BookId == null) { var nonNullBookScripts = bookScripts.Where(b => b != null).Select(b => b.BookId); var nonNullBookScriptsStr = Join(";", nonNullBookScripts); var initialMessage = bookScript == null ? "BookScript is null." : "BookScript has null BookId."; throw new ApplicationException($"{initialMessage} Number of BookScripts: {bookScripts.Count}. " + $"BookScripts which are NOT null: {nonNullBookScriptsStr}"); } } try { bookScripts.Sort((a, b) => BCVRef.BookToNumber(a.BookId).CompareTo(BCVRef.BookToNumber(b.BookId))); } catch (NullReferenceException n) { // This code is an attempt to figure out how we are getting null reference exceptions on the Sort call (See PG-275 & PG-287) StringBuilder sb = new StringBuilder(); foreach (var bookScript in bookScripts) { sb.Append(Environment.NewLine).Append(bookScript.BookId).Append("(").Append(BCVRef.BookToNumber(bookScript.BookId)).Append(")"); } throw new NullReferenceException("Null reference exception while sorting books." + sb, n); } reportProgressAsPercent?.Invoke(100); return(bookScripts); }
public static List <BookScript> ParseProject(IEnumerable <UsxDocument> books, IStylesheet stylesheet, BackgroundWorker projectWorker) { var numBlocksPerBook = new ConcurrentDictionary <string, int>(); var blocksInBook = new ConcurrentDictionary <string, XmlNodeList>(); Parallel.ForEach(books, bookScript => { var nodeList = bookScript.GetChaptersAndParas(); blocksInBook.AddOrUpdate(bookScript.BookId, nodeList, (s, list) => nodeList); numBlocksPerBook.AddOrUpdate(bookScript.BookId, nodeList.Count, (s, i) => nodeList.Count); }); int allProjectBlocks = numBlocksPerBook.Values.Sum(); int completedProjectBlocks = 0; var bookScripts = new List <BookScript>(blocksInBook.Count); Parallel.ForEach(blocksInBook, book => { var bookId = book.Key; Logger.WriteEvent("Creating bookScript ({0})", bookId); var parser = new UsxParser(bookId, stylesheet, book.Value); var bookScript = new BookScript(bookId, parser.Parse()); SingleVoiceReason singleVoiceReason; bookScript.SingleVoice = BookMetadata.DefaultToSingleVoice(bookId, out singleVoiceReason); bookScript.PageHeader = parser.PageHeader; bookScript.MainTitle = parser.MainTitle; Logger.WriteEvent("Created bookScript ({0}, {1})", bookId, bookScript.BookId); lock (bookScripts) bookScripts.Add(bookScript); Logger.WriteEvent("Added bookScript ({0}, {1})", bookId, bookScript.BookId); completedProjectBlocks += numBlocksPerBook[bookId]; projectWorker.ReportProgress(MathUtilities.Percent(completedProjectBlocks, allProjectBlocks, 99)); }); // This code is an attempt to figure out how we are getting null reference exceptions on the Sort call (See PG-275 & PG-287) // The above call to lock bookScripts probably fixes the problem!!! :-) We hope... foreach (var bookScript in bookScripts) { if (bookScript == null || bookScript.BookId == null) { var nonNullBookScripts = bookScripts.Where(b => b != null).Select(b => b.BookId); var nonNullBookScriptsStr = string.Join(";", nonNullBookScripts); var initialMessage = bookScript == null ? "BookScript is null." : "BookScript has null BookId."; throw new ApplicationException(string.Format("{0} Number of BookScripts: {1}. BookScripts which are NOT null: {2}", initialMessage, bookScripts.Count, nonNullBookScriptsStr)); } } try { bookScripts.Sort((a, b) => BCVRef.BookToNumber(a.BookId).CompareTo(BCVRef.BookToNumber(b.BookId))); } catch (NullReferenceException n) { // This code is an attempt to figure out how we are getting null reference exceptions on the Sort call (See PG-275 & PG-287) StringBuilder sb = new StringBuilder(); foreach (var bookScript in bookScripts) { sb.Append(Environment.NewLine).Append(bookScript.BookId).Append("(").Append(BCVRef.BookToNumber(bookScript.BookId)).Append(")"); } throw new NullReferenceException("Null reference exception while sorting books." + sb, n); } projectWorker.ReportProgress(100); return(bookScripts); }