Skip to content

Commit

Permalink
Changed BackgroundWorkers in Project to async await
Browse files Browse the repository at this point in the history
  • Loading branch information
tombogle committed Oct 2, 2020
1 parent 3096fa9 commit 31fd5cd
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 109 deletions.
8 changes: 8 additions & 0 deletions Glyssen/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,14 @@ private void SetProject(Project project)
}

private void FinishSetProjectIfReady(object sender, EventArgs e)
{
if (InvokeRequired)
Invoke(new Action(FinishSetProjectIfReady));
else
FinishSetProjectIfReady();
}

private void FinishSetProjectIfReady()
{
if (m_project != null && (m_project.ProjectState & ProjectState.ReadyForUserInteraction) > 0)
FinishSetProject();
Expand Down
134 changes: 44 additions & 90 deletions GlyssenEngine/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ public void SetQuoteSystem(QuoteSystemStatus status, QuoteSystem system)
if (IsQuoteSystemReadyForParse && ProjectState == ProjectState.NeedsQuoteSystemConfirmation)
{
m_quoteSystem = system;
DoQuoteParse();
DoQuoteParseAsync();
}
else if ((quoteSystemChanged && !quoteSystemBeingSetForFirstTime) ||
(QuoteSystemStatus == QuoteSystemStatus.Reviewed &&
Expand Down Expand Up @@ -1344,7 +1344,7 @@ private void InitializeLoadedProject()
m_usxPercentComplete = 100;
if (QuoteSystem == null)
{
GuessAtQuoteSystem();
GuessAtQuoteSystemAsync();
UpdateControlFileVersion();
return;
}
Expand Down Expand Up @@ -1463,55 +1463,38 @@ private void ParseAndSetBooks(IEnumerable<UsxDocument> books, IStylesheet styles
ParseAndIncludeBooks(books, stylesheet);
}

private void ParseAndIncludeBooks(IEnumerable<UsxDocument> books, IStylesheet stylesheet, Action<BookScript> postParseAction = null)
private async Task ParseAndIncludeBooks(IEnumerable<UsxDocument> books, IStylesheet stylesheet, Action<BookScript> postParseAction = null)
{
if (Versification == null)
throw new NullReferenceException("What!!!");
ProjectState = ProjectState.Initial | (ProjectState & ProjectState.WritingSystemRecoveryInProcess);
var usxWorker = new BackgroundWorker {WorkerReportsProgress = true};
usxWorker.DoWork += UsxWorker_DoWork;
usxWorker.RunWorkerCompleted += UsxWorker_RunWorkerCompleted;
usxWorker.ProgressChanged += UsxWorker_ProgressChanged;

object[] parameters = {books, stylesheet, postParseAction};
usxWorker.RunWorkerAsync(parameters);
await Task.Run(() => {UsxParse(books, stylesheet, postParseAction);});
}

private void UsxWorker_DoWork(object sender, DoWorkEventArgs e)
private void UsxParse(IEnumerable<UsxDocument> books, IStylesheet stylesheet, Action<BookScript> postParseAction = null)
{
var parameters = (object[])e.Argument;
var books = (IEnumerable<UsxDocument>)parameters[0];
var stylesheet = (IStylesheet)parameters[1];
var postParseAction = parameters.Length > 2 ? (Action<BookScript>)parameters[2] : null;

var backgroundWorker = (BackgroundWorker)sender;

var parsedBooks = UsxParser.ParseBooks(books, stylesheet, i => backgroundWorker.ReportProgress(i));
var parsedBooks = UsxParser.ParseBooks(books, stylesheet, i =>
{
m_usxPercentComplete = i;
var pe = new ProgressChangedEventArgs(PercentInitialized, null);
OnReport(pe);
});

if (postParseAction != null)
{
foreach (var book in parsedBooks)
postParseAction(book);
}
e.Result = parsedBooks;
}

private void UsxWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
throw e.Error;

var bookScripts = (List<BookScript>)e.Result;

foreach (var bookScript in bookScripts)
foreach (var bookScript in parsedBooks)
{
// This code is an attempt to figure out how we are getting null reference exceptions when using the objects in the list (See PG-275 & PG-287)
if (bookScript?.BookId == null)
{
var nonNullBookScripts = bookScripts.Where(b => b != null).Select(b => b.BookId);
var nonNullBookScripts = parsedBooks.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}. " +
throw new ApplicationException($"{initialMessage} Number of BookScripts: {parsedBooks.Count}. " +
$"BookScripts which are NOT null: {nonNullBookScriptsStr}");
}

Expand All @@ -1520,12 +1503,12 @@ private void UsxWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEvent

if (m_books.Any())
{
foreach (var book in bookScripts)
foreach (var book in parsedBooks)
IncludeExistingBook(book);
}
else
{
m_books.AddRange(bookScripts);
m_books.AddRange(parsedBooks);
m_projectMetadata.ParserVersion = kParserVersion;
if (m_books.All(b => IsNullOrEmpty(b.PageHeader)))
ChapterAnnouncementStyle = ChapterAnnouncement.ChapterLabel;
Expand All @@ -1535,79 +1518,57 @@ private void UsxWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEvent
}

if (QuoteSystem == null)
GuessAtQuoteSystem();
GuessAtQuoteSystemAsync();
else if (IsQuoteSystemReadyForParse)
DoQuoteParse(bookScripts.Select(b => b.BookId));
DoQuoteParseAsync(parsedBooks.Select(b => b.BookId));
}

private void UsxWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
m_usxPercentComplete = e.ProgressPercentage;
var pe = new ProgressChangedEventArgs(PercentInitialized, null);
OnReport(pe);
}

private void GuessAtQuoteSystem()
private async Task GuessAtQuoteSystemAsync()
{
ProjectState = ProjectState.UsxComplete | (ProjectState & ProjectState.WritingSystemRecoveryInProcess);
var guessWorker = new BackgroundWorker {WorkerReportsProgress = true};
guessWorker.DoWork += GuessWorker_DoWork;
guessWorker.RunWorkerCompleted += GuessWorker_RunWorkerCompleted;
guessWorker.ProgressChanged += GuessWorker_ProgressChanged;
guessWorker.RunWorkerAsync();
await Task.Run(GuessAtQuoteSystem);
}

private void GuessWorker_DoWork(object sender, DoWorkEventArgs e)
{
e.Result = QuoteSystemGuesser.Guess(ControlCharacterVerseData.Singleton, m_books, Versification, out _,
sender as BackgroundWorker);
}

private void GuessWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
private void GuessAtQuoteSystem()
{
if (e.Error != null)
throw e.Error;

SetQuoteSystem(QuoteSystemStatus.Guessed, (QuoteSystem)e.Result);
var quoteSystem = QuoteSystemGuesser.Guess(ControlCharacterVerseData.Singleton, m_books, Versification, out _,
i =>
{
m_guessPercentComplete = i;
var pe = new ProgressChangedEventArgs(PercentInitialized, null);
OnReport(pe);
});

SetQuoteSystem(QuoteSystemStatus.Guessed, quoteSystem);
Save();
}

private void GuessWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
m_guessPercentComplete = e.ProgressPercentage;
var pe = new ProgressChangedEventArgs(PercentInitialized, null);
OnReport(pe);
}

private void DoQuoteParse(IEnumerable<string> booksToParse = null)
private async Task DoQuoteParseAsync(IEnumerable<string> booksToParse = null)
{
m_projectMetadata.ParserVersion = kParserVersion;
ProjectState = ProjectState.Parsing;
var quoteWorker = new BackgroundWorker {WorkerReportsProgress = true};
quoteWorker.DoWork += QuoteWorker_DoWork;
quoteWorker.RunWorkerCompleted += QuoteWorker_RunWorkerCompleted;
quoteWorker.ProgressChanged += QuoteWorker_ProgressChanged;
object[] parameters = {booksToParse};
quoteWorker.RunWorkerAsync(parameters);
}

private void QuoteWorker_DoWork(object sender, DoWorkEventArgs e)
{
var bookIds = (IEnumerable<string>)((object[])e.Argument)[0];
QuoteParser.ParseProject(this, sender as BackgroundWorker, bookIds);
await Task.Run(() => { DoQuoteParse(booksToParse);});
}

private void QuoteWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
private void DoQuoteParse(IEnumerable<string> bookIds)
{
if (e.Error != null)
try
{
QuoteParser.ParseProject(this, i =>
{
m_quotePercentComplete = i;
var pe = new ProgressChangedEventArgs(PercentInitialized, null);
OnReport(pe);
}, bookIds);
}
catch (Exception e)
{
#if DEBUG
Exception innerException;
if ((innerException = e.Error?.InnerException) != null)
if ((innerException = e.InnerException) != null)
Debug.WriteLine(innerException.Message + innerException.StackTrace);
#endif
throw e.Error;
throw;
}

ProjectState = ProjectState.QuoteParseComplete;
Expand All @@ -1628,13 +1589,6 @@ private void QuoteWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEve
QuoteParseCompleted?.Invoke(this, new EventArgs());
}

private void QuoteWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
m_quotePercentComplete = e.ProgressPercentage;
var pe = new ProgressChangedEventArgs(PercentInitialized, null);
OnReport(pe);
}

public int MaxProjectNameLength => Writer.GetMaxProjectNameLength(this);

public BookScript LoadExistingBookIfPossible(string bookId)
Expand Down
7 changes: 3 additions & 4 deletions GlyssenEngine/Quote/QuoteParser.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
Expand All @@ -21,7 +20,7 @@ namespace GlyssenEngine.Quote
{
public class QuoteParser
{
public static void ParseProject(Project project, BackgroundWorker projectWorker, IEnumerable<string> bookIdsToParse)
public static void ParseProject(Project project, Action<int> reportProgress, IEnumerable<string> bookIdsToParse)
{
var cvInfo = new ParserCharacterRepository(new CombinedCharacterVerseData(project), project.ReferenceText);

Expand All @@ -43,10 +42,10 @@ public static void ParseProject(Project project, BackgroundWorker projectWorker,
{
book.Blocks = new QuoteParser(cvInfo, book.BookId, blocksInBook[book], project.Versification).Parse().ToList();
completedProjectBlocks += numBlocksPerBook[book.BookId];
projectWorker.ReportProgress(MathUtilities.Percent(completedProjectBlocks, allProjectBlocks, 99));
reportProgress(MathUtilities.Percent(completedProjectBlocks, allProjectBlocks, 99));
});

projectWorker.ReportProgress(100);
reportProgress(100);
}

public static void SetQuoteSystem(QuoteSystem quoteSystem)
Expand Down
22 changes: 7 additions & 15 deletions GlyssenEngine/Quote/QuoteSystemGuesser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using Glyssen.Shared;
Expand Down Expand Up @@ -37,13 +36,13 @@ private static void IncrementScore(Dictionary<QuoteSystem, int> scores, QuoteSys
bestScore = scores[quoteSystem];
}

public static QuoteSystem Guess<T>(ICharacterVerseInfo cvInfo, List<T> bookList, ScrVers versification, out bool certain, BackgroundWorker worker = null) where T : IScrBook
public static QuoteSystem Guess<T>(ICharacterVerseInfo cvInfo, List<T> bookList, ScrVers versification, out bool certain, Action<int> reportProgress = null) where T : IScrBook
{
certain = false;
var bookCount = bookList.Count;
if (bookCount == 0)
{
ReportProgressComplete(worker);
reportProgress?.Invoke(100);
return QuoteSystem.Default;
}
var scores = QuoteSystem.UniquelyGuessableSystems.ToDictionary(s => s, s => 0);
Expand Down Expand Up @@ -73,8 +72,7 @@ public static QuoteSystem Guess<T>(ICharacterVerseInfo cvInfo, List<T> bookList,
var bookNum = bookTuple.Item1;
var book = bookTuple.Item2;

if (worker != null)
worker.ReportProgress(MathUtilities.Percent(++booksProcessed, bookCount));
reportProgress?.Invoke(MathUtilities.Percent(++booksProcessed, bookCount));

int versesAnalyzedForCurrentBook = 0;
int prevQuoteChapter = -1;
Expand Down Expand Up @@ -209,7 +207,7 @@ public static QuoteSystem Guess<T>(ICharacterVerseInfo cvInfo, List<T> bookList,
if (competitors.Count == 1)
{
certain = true;
ReportProgressComplete(worker);
reportProgress?.Invoke(100);
return competitors[0];
}

Expand Down Expand Up @@ -297,7 +295,7 @@ public static QuoteSystem Guess<T>(ICharacterVerseInfo cvInfo, List<T> bookList,

if (competitors.Any())
{
ReportProgressComplete(worker);
reportProgress?.Invoke(100);

if (competitors.Count == 1)
return competitors[0];
Expand Down Expand Up @@ -327,15 +325,15 @@ public static QuoteSystem Guess<T>(ICharacterVerseInfo cvInfo, List<T> bookList,
#if SHOWTESTINFO
Debug.WriteLine("Time-out guessing quote system.");
#endif
ReportProgressComplete(worker);
reportProgress?.Invoke(100);
return BestGuess(viableSystems, scores, bestScore, foundEndQuote);
}

prevQuoteChapter = quote.Chapter;
prevQuoteVerse = quote.Verse;
}
}
ReportProgressComplete(worker);
reportProgress?.Invoke(100);
return BestGuess(viableSystems, scores, bestScore, foundEndQuote);
}

Expand Down Expand Up @@ -427,11 +425,5 @@ private static QuoteSystem BestGuess(IEnumerable<QuoteSystem> viableSystems, Dic
// newSystem.AllLevels.Add(QuoteUtils.GenerateLevel3(newSystem, true));
// return newSystem;
//}

private static void ReportProgressComplete(BackgroundWorker worker)
{
if (worker != null)
worker.ReportProgress(100);
}
}
}

1 comment on commit 31fd5cd

@palaso-bob
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TeamCity Glyssen / Glyssen pull requests (64-bit) Build 1.5.2-replace-backgroundworker-with-async-await.22 outcome was FAILURE
Summary: Tests passed: 2535, ignored: 19; exit code 1 (Step: Release - Test, Installers (MSBuild)) (new) Build time: 00:15:34

Please sign in to comment.