From 413a019c9732682a7f03a1b003ad4b044ef2b5e8 Mon Sep 17 00:00:00 2001 From: David Smith Date: Tue, 10 Jan 2017 19:46:20 -0600 Subject: [PATCH] Convert function to run tally on votes to async to avoid UI jank. Update all references. --- TallyCore/Tally.cs | 8 ++++---- TallyCore/Votes/IVoteCounter.cs | 4 ++-- TallyCore/Votes/VoteCounter.cs | 26 ++++++++++++++++++++++---- TallyUnitTest/VoteConstructorTests.cs | 25 +++++++++++++------------ TallyUnitTest/VoteCounterTests.cs | 6 ++++-- TallyUnitTest/VoteTests.cs | 8 ++++---- 6 files changed, 49 insertions(+), 28 deletions(-) diff --git a/TallyCore/Tally.cs b/TallyCore/Tally.cs index c2718207..fc3538cb 100644 --- a/TallyCore/Tally.cs +++ b/TallyCore/Tally.cs @@ -118,13 +118,13 @@ private void Options_PropertyChanged(object sender, PropertyChangedEventArgs e) /// /// The quest that sent the notification. /// Info about a property of the quest that changed. - private void Quest_PropertyChanged(object sender, PropertyChangedEventArgs e) + private async void Quest_PropertyChanged(object sender, PropertyChangedEventArgs e) { IQuest quest = sender as IQuest; if (quest != null && quest == VoteCounter.Instance.Quest) { if (e.PropertyName == "PartitionMode") - UpdateTally(); + await UpdateTally(); } } #endregion @@ -253,12 +253,12 @@ public void ClearPageCache() /// /// Process the results of the tally through the vote counter, and update the output. /// - private void UpdateTally() + private async Task UpdateTally() { if (VoteCounter.Instance.Quest != null) { // Tally the votes from the loaded pages. - VoteCounter.Instance.TallyPosts(); + await VoteCounter.Instance.TallyPosts().ConfigureAwait(false); // Compose the final result string from the compiled votes. UpdateResults(); diff --git a/TallyCore/Votes/IVoteCounter.cs b/TallyCore/Votes/IVoteCounter.cs index 54dbe285..5a9f0f9d 100644 --- a/TallyCore/Votes/IVoteCounter.cs +++ b/TallyCore/Votes/IVoteCounter.cs @@ -12,8 +12,8 @@ public interface IVoteCounter : INotifyPropertyChanged IQuest Quest { get; set; } Task TallyVotes(IQuest quest, ThreadRangeInfo startInfo, List> pages); - void TallyPosts(); - void TallyPosts(IQuest quest); + Task TallyPosts(); + Task TallyPosts(IQuest quest); List PostsList { get; } void Reset(); diff --git a/TallyCore/Votes/VoteCounter.cs b/TallyCore/Votes/VoteCounter.cs index 15f70163..fc37ebc5 100644 --- a/TallyCore/Votes/VoteCounter.cs +++ b/TallyCore/Votes/VoteCounter.cs @@ -178,7 +178,7 @@ public async Task TallyVotes(IQuest quest, ThreadRangeInfo startInfo, List PostsList = PostsList.Distinct().OrderBy(p => p.Number).ToList(); - TallyPosts(); + await TallyPosts().ConfigureAwait(false); return true; } @@ -187,22 +187,33 @@ public async Task TallyVotes(IQuest quest, ThreadRangeInfo startInfo, List /// Run TallyPosts using the provided quest. /// /// The quest that will be used for tallying parameters. - public void TallyPosts(IQuest quest) + public async Task TallyPosts(IQuest quest) { Quest = quest; - TallyPosts(); + await TallyPosts().ConfigureAwait(false); } /// /// Construct the tally results based on the stored list of posts. + /// Run async so that it doesn't cause UI jank. /// - public void TallyPosts() + public async Task TallyPosts() { Reset(); if (PostsList == null || PostsList.Count == 0) return; + await Task.Run(() => PreprocessPlans()); + await Task.Run(() => ProcessPosts()); + } + + /// + /// The first half of tallying posts involves doing the preprocessing + /// work on the plans in the post list. + /// + private void PreprocessPlans() + { // Preprocessing Phase 1 (Only plans with contents are counted as plans.) foreach (var post in PostsList) { @@ -230,7 +241,14 @@ public void TallyPosts() { post.SetWorkingVote(p => VoteConstructor.GetWorkingVote(p)); } + } + /// + /// The second half of tallying the posts involves cycling through for + /// as long as future references need to be handled. + /// + private void ProcessPosts() + { var unprocessed = PostsList; // Loop as long as there are any more to process. diff --git a/TallyUnitTest/VoteConstructorTests.cs b/TallyUnitTest/VoteConstructorTests.cs index 57245cca..acf3877f 100644 --- a/TallyUnitTest/VoteConstructorTests.cs +++ b/TallyUnitTest/VoteConstructorTests.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using NetTally.Utility; namespace NetTally.Tests @@ -136,7 +137,7 @@ [x] Head over to Oriko's. [TestMethod] - public void ProcessPostContentsWholeWithReferralTest1() + public async Task ProcessPostContentsWholeWithReferralTest1() { sampleQuest.PartitionMode = PartitionMode.None; @@ -164,7 +165,7 @@ [x] Head over to Oriko's. VoteCounter.Instance.PostsList.Add(p1); VoteCounter.Instance.PostsList.Add(p2); - VoteCounter.Instance.TallyPosts(sampleQuest); + await VoteCounter.Instance.TallyPosts(sampleQuest); var votes = VoteCounter.Instance.GetVotesCollection(VoteType.Vote); var voters = VoteCounter.Instance.GetVotersCollection(VoteType.Vote); @@ -174,7 +175,7 @@ [x] Head over to Oriko's. } [TestMethod] - public void ProcessPostContentsBlockWithReferralTest1() + public async Task ProcessPostContentsBlockWithReferralTest1() { sampleQuest.PartitionMode = PartitionMode.ByBlock; @@ -200,7 +201,7 @@ [x] Head over to Oriko's. VoteCounter.Instance.PostsList.Add(p1); VoteCounter.Instance.PostsList.Add(p2); - VoteCounter.Instance.TallyPosts(sampleQuest); + await VoteCounter.Instance.TallyPosts(sampleQuest); var votes = VoteCounter.Instance.GetVotesCollection(VoteType.Vote); var voters = VoteCounter.Instance.GetVotersCollection(VoteType.Vote); @@ -210,7 +211,7 @@ [x] Head over to Oriko's. } [TestMethod] - public void ProcessPostContentsLineWithReferralTest1() + public async Task ProcessPostContentsLineWithReferralTest1() { sampleQuest.PartitionMode = PartitionMode.ByLine; @@ -236,7 +237,7 @@ [x] Head over to Oriko's. VoteCounter.Instance.PostsList.Add(p1); VoteCounter.Instance.PostsList.Add(p2); - VoteCounter.Instance.TallyPosts(sampleQuest); + await VoteCounter.Instance.TallyPosts(sampleQuest); var votes = VoteCounter.Instance.GetVotesCollection(VoteType.Vote); var voters = VoteCounter.Instance.GetVotersCollection(VoteType.Vote); @@ -247,7 +248,7 @@ [x] Head over to Oriko's. [TestMethod] - public void ProcessPostContentsWholeWithReferralTest2() + public async Task ProcessPostContentsWholeWithReferralTest2() { sampleQuest.PartitionMode = PartitionMode.None; @@ -273,7 +274,7 @@ [x] Head over to Oriko's. VoteCounter.Instance.PostsList.Add(p1); VoteCounter.Instance.PostsList.Add(p2); - VoteCounter.Instance.TallyPosts(sampleQuest); + await VoteCounter.Instance.TallyPosts(sampleQuest); var votes = VoteCounter.Instance.GetVotesCollection(VoteType.Vote); var voters = VoteCounter.Instance.GetVotersCollection(VoteType.Vote); @@ -283,7 +284,7 @@ [x] Head over to Oriko's. } [TestMethod] - public void ProcessPostContentsBlockWithReferralTest2() + public async Task ProcessPostContentsBlockWithReferralTest2() { sampleQuest.PartitionMode = PartitionMode.ByBlock; @@ -310,7 +311,7 @@ [x] Head over to Oriko's. VoteCounter.Instance.PostsList.Add(p1); VoteCounter.Instance.PostsList.Add(p2); - VoteCounter.Instance.TallyPosts(sampleQuest); + await VoteCounter.Instance.TallyPosts(sampleQuest); var votes = VoteCounter.Instance.GetVotesCollection(VoteType.Vote); var voters = VoteCounter.Instance.GetVotersCollection(VoteType.Vote); @@ -321,7 +322,7 @@ [x] Head over to Oriko's. } [TestMethod] - public void ProcessPostContentsLineWithReferralTest2() + public async Task ProcessPostContentsLineWithReferralTest2() { sampleQuest.PartitionMode = PartitionMode.ByLine; @@ -348,7 +349,7 @@ [x] Head over to Oriko's. VoteCounter.Instance.PostsList.Add(p1); VoteCounter.Instance.PostsList.Add(p2); - VoteCounter.Instance.TallyPosts(sampleQuest); + await VoteCounter.Instance.TallyPosts(sampleQuest); var votes = VoteCounter.Instance.GetVotesCollection(VoteType.Vote); var voters = VoteCounter.Instance.GetVotersCollection(VoteType.Vote); diff --git a/TallyUnitTest/VoteCounterTests.cs b/TallyUnitTest/VoteCounterTests.cs index c6c7d77d..5eda138f 100644 --- a/TallyUnitTest/VoteCounterTests.cs +++ b/TallyUnitTest/VoteCounterTests.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using NetTally.Utility; namespace NetTally.Tests { @@ -507,14 +509,14 @@ public void TallyVotesTest() } [TestMethod] - public void NameReferenceTest() + public async Task NameReferenceTest() { // Check for non-case sensitivity in referencing other voters. PostComponents p1 = new PostComponents("Beyogi", "12345", "[x] Vote for something"); PostComponents p2 = new PostComponents("Mini", "12345", "[x] beyogi"); VoteCounter.Instance.PostsList.Add(p1); VoteCounter.Instance.PostsList.Add(p2); - VoteCounter.Instance.TallyPosts(sampleQuest); + await VoteCounter.Instance.TallyPosts(sampleQuest); Assert.AreEqual(2, VoteCounter.Instance.GetVotersCollection(VoteType.Vote).Count); Assert.AreEqual(1, VoteCounter.Instance.GetVotesCollection(VoteType.Vote).Count); diff --git a/TallyUnitTest/VoteTests.cs b/TallyUnitTest/VoteTests.cs index 0fcc97df..a7efbe3f 100644 --- a/TallyUnitTest/VoteTests.cs +++ b/TallyUnitTest/VoteTests.cs @@ -29,7 +29,7 @@ public void Initialize() #endregion #region Test Harness - public void TestSinglePostParsing(string vote, List results) + public async Task TestSinglePostParsing(string vote, List results) { string author = "User1"; string postId = "123456"; @@ -38,7 +38,7 @@ public void TestSinglePostParsing(string vote, List results) PostComponents post = new PostComponents(author, postId, vote, postNumber); VoteCounter.Instance.PostsList.Add(post); - VoteCounter.Instance.TallyPosts(sampleQuest); + await VoteCounter.Instance.TallyPosts(sampleQuest); var votes = GetVotesBy(author, VoteType.Vote); @@ -51,7 +51,7 @@ public List GetVotesBy(string author, VoteType voteType) return votes.Where(v => v.Value.Contains(author)).Select(v => v.Key).ToList(); } - public void TestReferencePostParsing(List votes, List authors, List> results) + public async Task TestReferencePostParsing(List votes, List authors, List> results) { for (int i = 0; i < votes.Count; i++) { @@ -62,7 +62,7 @@ public void TestReferencePostParsing(List votes, List authors, L VoteCounter.Instance.PostsList.Add(post); } - VoteCounter.Instance.TallyPosts(sampleQuest); + await VoteCounter.Instance.TallyPosts(sampleQuest); for (int i = 0; i < results.Count; i++) {