public async void Run(IBackgroundTaskInstance taskInstance) { AddQuestionsResult result = null; BackgroundTaskDeferral deferral = taskInstance.GetDeferral(); #if DEBUG InvokeSimpleToast("Hello from " + taskInstance.Task.Name); #endif try { result = await FeedManager.QueryWebsitesAsync(); #if DEBUG InvokeSimpleToast(String.Format( "There are {0} new questions and {1} updated questions.", result.AddedQuestions, result.UpdatedQuestions)); #endif } catch (Exception ex) { Debug.WriteLine(ex); #if DEBUG InvokeSimpleToast(ex.Message); #endif } deferral.Complete(); }
// This method can be call simultaneously. Make sure only one thread is touching it. public static AddQuestionsResult AddQuestions(string websiteUrl, SyndicationFeed feed, bool skipLatestPubDate) { AddQuestionsResult globalResult = new AddQuestionsResult(); DateTimeOffset latestPubDate = SettingsManager.GetLastestPubDate(websiteUrl); DateTimeOffset newLatestPubDate = DateTimeOffset.MinValue; Debug.WriteLine("{0} Current LastestPubDate is {1}.", websiteUrl, latestPubDate); // Wait until the event is set by another thread. addEvent.WaitOne(); try { CheckSettingsAreLoaded(); foreach (SyndicationItem item in feed.Items) { AddQuestionResult result = AddQuestionResult.None; if (skipLatestPubDate || DateTimeOffset.Compare(item.PublishedDate.DateTime, latestPubDate) > 0) { result = AddQuestion(websiteUrl, item); // Chances are we need to update the LatestPubDate. if (result == AddQuestionResult.Added && item.PublishedDate > newLatestPubDate) { newLatestPubDate = item.PublishedDate; Debug.WriteLine("{0} New LastestPubDate is {1}.", websiteUrl, newLatestPubDate); } } else { result = UpdateQuestion(websiteUrl, item); } switch (result) { case AddQuestionResult.Added: globalResult.AddedQuestions++; break; case AddQuestionResult.Updated: globalResult.UpdatedQuestions++; break; } } // If the quesiton list did not change, there should not be a new LatestPubDate. if (globalResult.AddedQuestions > 0) { SettingsManager.SetLastestPubDate(websiteUrl, newLatestPubDate); } return globalResult; } finally { // Set the event, so other threads waiting on it can do their job. addEvent.Set(); } }
public static IAsyncOperation <AddQuestionsResult> QueryTagAsync(string websiteUrl, string tagEncoded) { return(AsyncInfo.Run(async(cancellationToken) => { // Retrieve questions, skip the LatestPubDate validation and add all questions. AddQuestionsResult result = await FeedManager.QuerySingleWebsiteAsync(websiteUrl, tagEncoded, true); // Only limit and save questions if list changed. if (result.AddedQuestions > 0 || result.UpdatedQuestions > 0) { uint removedQuestions = await QuestionsManager.RemoveQuestionsInReadList(); await QuestionsManager.LimitTo150AndSaveAsync(); FeedManager.UpdateTileAndBadge(); } return result; })); }
// 1. Load settings. // 2. query -> Retrieve feeds. // 3. skipLatestPubDate -> Add questions. // 4. Sort questions (needed to show tile and badge). // 5. Update tile. // 6. Update badge. // TODO: Maybe check for buzz words here. public static IAsyncOperation <AddQuestionsResult> QueryWebsitesAsync() { return(AsyncInfo.Run(async(cancellationToken) => { SettingsManager.Load(); await QuestionsManager.LoadAsync(); // Query websites in parallel. List <Task <AddQuestionsResult> > tasks = new List <Task <AddQuestionsResult> >(); IEnumerable <string> keys = SettingsManager.GetWebsiteKeys(); foreach (string website in keys) { string query = SettingsManager.ConcatenateAllTags(website); tasks.Add(QuerySingleWebsiteAsync(website, query, false).AsTask()); } if (tasks.Count == 0) { // There is nothing to wait. return new AddQuestionsResult(); } await Task.Factory.ContinueWhenAll(tasks.ToArray(), (tasks2) => {}); // Add up the results. AddQuestionsResult result = new AddQuestionsResult(); foreach (Task <AddQuestionsResult> task in tasks) { AddQuestionsResult taskResult = task.Result; result.AddedQuestions += taskResult.AddedQuestions; result.UpdatedQuestions += taskResult.UpdatedQuestions; if (!taskResult.FileFound) { result.FileFound = false; } } Debug.WriteLine( "{0} questions added, {0} questions modified.", result.AddedQuestions, result.UpdatedQuestions); // Only limit and save questions if list changed. if (result.AddedQuestions > 0 || result.UpdatedQuestions > 0) { uint removedQuestions = await QuestionsManager.RemoveQuestionsInReadList(); await QuestionsManager.LimitTo150AndSaveAsync(); UpdateTileAndBadge(); SettingsManager.SaveLocal(); // Save updated latestPubDate. } // Update last query date-time, only if all queries were successful. if (result.FileFound) { SettingsManager.LatestQueryDate = DateTimeOffset.Now; } return result; })); }
public static IAsyncOperation <AddQuestionsResult> QuerySingleWebsiteAsync( string websiteUrl, string query, bool skipLatestPubDate) { return(AsyncInfo.Run(async(cancellationToken) => { AddQuestionsResult result = new AddQuestionsResult(); Uri uri; if (!SettingsManager.TryCreateUri(websiteUrl, query, out uri)) { Debugger.Break(); } SyndicationFeed feed = null; try { client.BypassCacheOnRetrieve = true; feed = await client.RetrieveFeedAsync(uri); } catch (Exception ex) { Debug.WriteLine("{0} {1}", websiteUrl, ex.Message); int hr = ex.HResult; int facility = (hr & 0x7FFF0000) / 0xFFFF; int error = hr & 0xFFFF; const int WEB_E_INVALID_XML = unchecked ((int)0x83750002); const int FACILITY_WIN32 = 7; const int FACILITY_HTTP = 25; const int NOT_FOUND = 404; if (hr == WEB_E_INVALID_XML) { // An invalid XML is equivalent to file not found. result.FileFound = false; return result; } else if (facility == FACILITY_HTTP && error == NOT_FOUND) { result.FileFound = false; return result; } else if (facility == FACILITY_HTTP) { // Swallow HTTP errors. Treat them as file not found. result.FileFound = false; return result; } else if (facility == FACILITY_WIN32 && error > 12001 && error < 12156) { // Swallow WININET errors. Treat as file not found. result.FileFound = false; return result; } else { throw; } } result = QuestionsManager.AddQuestions(websiteUrl, feed, skipLatestPubDate); result.FileFound = true; return result; })); }
// This method can be call simultaneously. Make sure only one thread is touching it. public static AddQuestionsResult AddQuestions(string websiteUrl, SyndicationFeed feed, bool skipLatestPubDate) { AddQuestionsResult globalResult = new AddQuestionsResult(); DateTimeOffset latestPubDate = SettingsManager.GetLastestPubDate(websiteUrl); DateTimeOffset newLatestPubDate = DateTimeOffset.MinValue; Debug.WriteLine("{0} Current LastestPubDate is {1}.", websiteUrl, latestPubDate); // Wait until the event is set by another thread. addEvent.WaitOne(); try { CheckSettingsAreLoaded(); foreach (SyndicationItem item in feed.Items) { AddQuestionResult result = AddQuestionResult.None; if (skipLatestPubDate || DateTimeOffset.Compare(item.PublishedDate.DateTime, latestPubDate) > 0) { result = AddQuestion(websiteUrl, item); // Chances are we need to update the LatestPubDate. if (result == AddQuestionResult.Added && item.PublishedDate > newLatestPubDate) { newLatestPubDate = item.PublishedDate; Debug.WriteLine("{0} New LastestPubDate is {1}.", websiteUrl, newLatestPubDate); } } else { result = UpdateQuestion(websiteUrl, item); } switch (result) { case AddQuestionResult.Added: globalResult.AddedQuestions++; break; case AddQuestionResult.Updated: globalResult.UpdatedQuestions++; break; } } // If the quesiton list did not change, there should not be a new LatestPubDate. if (globalResult.AddedQuestions > 0) { SettingsManager.SetLastestPubDate(websiteUrl, newLatestPubDate); } return(globalResult); } finally { // Set the event, so other threads waiting on it can do their job. addEvent.Set(); } }
public static IAsyncOperation<AddQuestionsResult> QuerySingleWebsiteAsync( string websiteUrl, string query, bool skipLatestPubDate) { return AsyncInfo.Run(async (cancellationToken) => { AddQuestionsResult result = new AddQuestionsResult(); Uri uri; if (!SettingsManager.TryCreateUri(websiteUrl, query, out uri)) { Debugger.Break(); } SyndicationFeed feed = null; try { client.BypassCacheOnRetrieve = true; feed = await client.RetrieveFeedAsync(uri); } catch (Exception ex) { Debug.WriteLine("{0} {1}", websiteUrl, ex.Message); int hr = ex.HResult; int facility = (hr & 0x7FFF0000) / 0xFFFF; int error = hr & 0xFFFF; const int WEB_E_INVALID_XML = unchecked((int)0x83750002); const int FACILITY_WIN32 = 7; const int FACILITY_HTTP = 25; const int NOT_FOUND = 404; if (hr == WEB_E_INVALID_XML) { // An invalid XML is equivalent to file not found. result.FileFound = false; return result; } else if (facility == FACILITY_HTTP && error == NOT_FOUND) { result.FileFound = false; return result; } else if (facility == FACILITY_HTTP) { // Swallow HTTP errors. Treat them as file not found. result.FileFound = false; return result; } else if (facility == FACILITY_WIN32 && error > 12001 && error < 12156) { // Swallow WININET errors. Treat as file not found. result.FileFound = false; return result; } else { throw; } } result = QuestionsManager.AddQuestions(websiteUrl, feed, skipLatestPubDate); result.FileFound = true; return result; }); }
// 1. Load settings. // 2. query -> Retrieve feeds. // 3. skipLatestPubDate -> Add questions. // 4. Sort questions (needed to show tile and badge). // 5. Update tile. // 6. Update badge. // TODO: Maybe check for buzz words here. public static IAsyncOperation<AddQuestionsResult> QueryWebsitesAsync() { return AsyncInfo.Run(async (cancellationToken) => { SettingsManager.Load(); await QuestionsManager.LoadAsync(); // Query websites in parallel. List<Task<AddQuestionsResult>> tasks = new List<Task<AddQuestionsResult>>(); IEnumerable<string> keys = SettingsManager.GetWebsiteKeys(); foreach (string website in keys) { string query = SettingsManager.ConcatenateAllTags(website); tasks.Add(QuerySingleWebsiteAsync(website, query, false).AsTask()); } if (tasks.Count == 0) { // There is nothing to wait. return new AddQuestionsResult(); } await Task.Factory.ContinueWhenAll(tasks.ToArray(), (tasks2) => {}); // Add up the results. AddQuestionsResult result = new AddQuestionsResult(); foreach (Task<AddQuestionsResult> task in tasks) { AddQuestionsResult taskResult = task.Result; result.AddedQuestions += taskResult.AddedQuestions; result.UpdatedQuestions += taskResult.UpdatedQuestions; if (!taskResult.FileFound) { result.FileFound = false; } } Debug.WriteLine( "{0} questions added, {0} questions modified.", result.AddedQuestions, result.UpdatedQuestions); // Only limit and save questions if list changed. if (result.AddedQuestions > 0 || result.UpdatedQuestions > 0) { uint removedQuestions = await QuestionsManager.RemoveQuestionsInReadList(); await QuestionsManager.LimitTo150AndSaveAsync(); UpdateTileAndBadge(); SettingsManager.SaveLocal(); // Save updated latestPubDate. } // Update last query date-time, only if all queries were successful. if (result.FileFound) { SettingsManager.LatestQueryDate = DateTimeOffset.Now; } return result; }); }