/// <summary> /// Use in place of CollectionChanged Adder /// </summary> /// <param name="objTag">Tag to associate with added delegate</param> /// <param name="funcDelegateToAdd">Delegate to add to CollectionChanged</param> /// <returns>True if delegate was successfully added, false if a delegate already exists with the associated tag.</returns> public async ValueTask <bool> AddTaggedCollectionChangedAsync(object objTag, NotifyCollectionChangedEventHandler funcDelegateToAdd) { IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync(); try { (bool blnSuccess, HashSet <NotifyCollectionChangedEventHandler> setFuncs) = await _dicTaggedAddedDelegates.TryGetValueAsync(objTag); if (!blnSuccess) { setFuncs = new HashSet <NotifyCollectionChangedEventHandler>(); await _dicTaggedAddedDelegates.AddAsync(objTag, setFuncs); } if (setFuncs.Add(funcDelegateToAdd)) { base.CollectionChanged += funcDelegateToAdd; return(true); } } finally { await objLocker.DisposeAsync(); } Utils.BreakIfDebug(); return(false); }
/// <summary> /// Get the compiled Xsl Transform of an Xsl file. Will throw exceptions if anything goes awry. /// If we've already compiled the same Xsl Transform before, we'll fetch the cached version of that transform instead of repeating it. /// Uses flag hack method design outlined here to avoid locking: /// https://docs.microsoft.com/en-us/archive/msdn-magazine/2015/july/async-programming-brownfield-async-development /// </summary> /// <param name="blnSync">Flag for whether method should always use synchronous code or not.</param> /// <param name="strXslFilePath">Absolute path to the Xsl file to be transformed.</param> /// <returns>The compiled Xsl transform of <paramref name="strXslFilePath"/>.</returns> private static async Task <XslCompiledTransform> GetTransformForFileCoreAsync(bool blnSync, string strXslFilePath) { if (!File.Exists(strXslFilePath)) { throw new FileNotFoundException(nameof(strXslFilePath)); } DateTime datLastWriteTimeUtc = File.GetLastWriteTimeUtc(strXslFilePath); XslCompiledTransform objReturn; bool blnSuccess; Tuple <DateTime, XslCompiledTransform> tupCachedData; if (blnSync) { // ReSharper disable once MethodHasAsyncOverload blnSuccess = s_dicCompiledTransforms.TryGetValue(strXslFilePath, out tupCachedData); } else { (blnSuccess, tupCachedData) = await s_dicCompiledTransforms.TryGetValueAsync(strXslFilePath); } if (!blnSuccess || tupCachedData.Item1 <= datLastWriteTimeUtc) { #if DEBUG objReturn = new XslCompiledTransform(true); #else objReturn = new XslCompiledTransform(); #endif if (blnSync) { objReturn.Load(strXslFilePath); // ReSharper disable once MethodHasAsyncOverload s_dicCompiledTransforms.Remove(strXslFilePath); // ReSharper disable once MethodHasAsyncOverload s_dicCompiledTransforms.TryAdd( strXslFilePath, new Tuple <DateTime, XslCompiledTransform>(datLastWriteTimeUtc, objReturn)); } else { await Task.Run(() => objReturn.Load(strXslFilePath)); await s_dicCompiledTransforms.RemoveAsync(strXslFilePath); await s_dicCompiledTransforms.TryAddAsync( strXslFilePath, new Tuple <DateTime, XslCompiledTransform>(datLastWriteTimeUtc, objReturn)); } } else { objReturn = tupCachedData.Item2; } return(objReturn); }
public static async ValueTask <TimeSpan> ElapsedAsync(string taskname) { (bool blnSuccess, TimeSpan objStartTimeSpan) = await s_DictionaryStarts.TryGetValueAsync(taskname); if (blnSuccess) { return(s_Time.Elapsed - objStartTimeSpan); } return(TimeSpan.Zero); }
/// <summary> /// Generates a character cache, which prevents us from repeatedly loading XmlNodes or caching a full character. /// </summary> /// <param name="strFile"></param> private async Task <TreeNode> CacheCharacters(string strFile) { if (!File.Exists(strFile)) { Program.ShowMessageBox( this, string.Format(GlobalSettings.CultureInfo, await LanguageManager.GetStringAsync("Message_File_Cannot_Be_Accessed"), strFile)); return(null); } ThreadSafeList <XPathNavigator> lstCharacterXmlStatblocks = new ThreadSafeList <XPathNavigator>(3); try { try { using (ZipArchive zipArchive = ZipFile.Open(strFile, ZipArchiveMode.Read, Encoding.GetEncoding(850))) { // NOTE: Cannot parallelize because ZipFile.Open creates one handle on the entire zip file that gets messed up if we try to get it to read multiple files at once foreach (ZipArchiveEntry entry in zipArchive.Entries) { string strEntryFullName = entry.FullName; if (strEntryFullName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase) && strEntryFullName.StartsWith("statblocks_xml", StringComparison.Ordinal)) { // If we run into any problems loading the character cache, fail out early. try { using (StreamReader sr = new StreamReader(entry.Open(), true)) { await Task.Run(() => { XPathDocument xmlSourceDoc; using (XmlReader objXmlReader = XmlReader.Create(sr, GlobalSettings.SafeXmlReaderSettings)) xmlSourceDoc = new XPathDocument(objXmlReader); XPathNavigator objToAdd = xmlSourceDoc.CreateNavigator(); lstCharacterXmlStatblocks.Add(objToAdd); }); } } // If we run into any problems loading the character cache, fail out early. catch (IOException) { Utils.BreakIfDebug(); } catch (XmlException) { Utils.BreakIfDebug(); } } else if (strEntryFullName.StartsWith("images", StringComparison.Ordinal) && strEntryFullName.Contains('.')) { string strKey = Path.GetFileName(strEntryFullName); using (Bitmap bmpMugshot = new Bitmap(entry.Open(), true)) { Bitmap bmpNewMugshot = bmpMugshot.PixelFormat == PixelFormat.Format32bppPArgb ? bmpMugshot.Clone() as Bitmap // Clone makes sure file handle is closed : bmpMugshot.ConvertPixelFormat(PixelFormat.Format32bppPArgb); while (!await _dicImages.TryAddAsync(strKey, bmpNewMugshot)) { (bool blnSuccess, Bitmap bmpOldMugshot) = await _dicImages.TryRemoveAsync(strKey); if (blnSuccess) { bmpOldMugshot?.Dispose(); } } } } } } } catch (IOException) { Program.ShowMessageBox( this, string.Format(GlobalSettings.CultureInfo, await LanguageManager.GetStringAsync("Message_File_Cannot_Be_Accessed"), strFile)); return(null); } catch (NotSupportedException) { Program.ShowMessageBox( this, string.Format(GlobalSettings.CultureInfo, await LanguageManager.GetStringAsync("Message_File_Cannot_Be_Accessed"), strFile)); return(null); } catch (UnauthorizedAccessException) { Program.ShowMessageBox( this, await LanguageManager.GetStringAsync("Message_Insufficient_Permissions_Warning")); return(null); } string strFileText = await strFile.CheapReplaceAsync(Utils.GetStartupPath, () => '<' + Application.ProductName + '>'); TreeNode nodRootNode = new TreeNode { Text = strFileText, ToolTipText = strFileText }; XPathNavigator xmlMetatypesDocument = await XmlManager.LoadXPathAsync("metatypes.xml"); foreach (XPathNavigator xmlCharacterDocument in lstCharacterXmlStatblocks) { XPathNavigator xmlBaseCharacterNode = xmlCharacterDocument.SelectSingleNode("/document/public/character"); if (xmlBaseCharacterNode != null) { HeroLabCharacterCache objCache = new HeroLabCharacterCache { PlayerName = xmlBaseCharacterNode.SelectSingleNode("@playername")?.Value ?? string.Empty }; string strNameString = xmlBaseCharacterNode.SelectSingleNode("@name")?.Value ?? string.Empty; objCache.CharacterId = strNameString; if (!string.IsNullOrEmpty(strNameString)) { int intAsIndex = strNameString.IndexOf(" as ", StringComparison.Ordinal); if (intAsIndex != -1) { objCache.CharacterName = strNameString.Substring(0, intAsIndex); objCache.CharacterAlias = strNameString.Substring(intAsIndex).TrimStart(" as ").Trim('\''); } else { objCache.CharacterName = strNameString; } } string strRaceString = xmlBaseCharacterNode.SelectSingleNode("race/@name")?.Value; if (strRaceString == "Metasapient") { strRaceString = "A.I."; } if (!string.IsNullOrEmpty(strRaceString)) { foreach (XPathNavigator xmlMetatype in xmlMetatypesDocument.Select( "/chummer/metatypes/metatype")) { string strMetatypeName = xmlMetatype.SelectSingleNode("name")?.Value ?? string.Empty; if (strMetatypeName == strRaceString) { objCache.Metatype = strMetatypeName; objCache.Metavariant = "None"; break; } foreach (XPathNavigator xmlMetavariant in await xmlMetatype.SelectAndCacheExpressionAsync("metavariants/metavariant")) { string strMetavariantName = xmlMetavariant.SelectSingleNode("name")?.Value ?? string.Empty; if (strMetavariantName == strRaceString) { objCache.Metatype = strMetatypeName; objCache.Metavariant = strMetavariantName; break; } } } } objCache.Description = xmlBaseCharacterNode.SelectSingleNode("personal/description")?.Value; objCache.Karma = xmlBaseCharacterNode.SelectSingleNode("karma/@total")?.Value ?? "0"; objCache.Essence = xmlBaseCharacterNode .SelectSingleNode("attributes/attribute[@name = \"Essence\"]/@text")?.Value; objCache.BuildMethod = xmlBaseCharacterNode.SelectSingleNode("creation/bp/@total")?.ValueAsInt <= 100 ? CharacterBuildMethod.Priority : CharacterBuildMethod.Karma; string strSettingsSummary = xmlBaseCharacterNode.SelectSingleNode("settings/@summary")?.Value; if (!string.IsNullOrEmpty(strSettingsSummary)) { int intSemicolonIndex; bool blnDoFullHouse = false; int intSourcebooksIndex = strSettingsSummary.IndexOf("Core Rulebooks:", StringComparison.OrdinalIgnoreCase); if (intSourcebooksIndex != -1) { intSemicolonIndex = strSettingsSummary.IndexOf(';', intSourcebooksIndex); if (intSourcebooksIndex + 16 < intSemicolonIndex) { blnDoFullHouse = true; // We probably have multiple books enabled, so use Full House instead } } string strHeroLabSettingsName = "Standard"; int intCharCreationSystemsIndex = strSettingsSummary.IndexOf("Character Creation Systems:", StringComparison.OrdinalIgnoreCase); if (intCharCreationSystemsIndex != -1) { intSemicolonIndex = strSettingsSummary.IndexOf(';', intCharCreationSystemsIndex); if (intCharCreationSystemsIndex + 28 <= intSemicolonIndex) { strHeroLabSettingsName = strSettingsSummary.Substring( intCharCreationSystemsIndex + 28, strSettingsSummary.IndexOf( ';', intCharCreationSystemsIndex) - 28 - intCharCreationSystemsIndex) .Trim(); if (strHeroLabSettingsName == "Established Runners") { strHeroLabSettingsName = "Standard"; } } } if (strHeroLabSettingsName == "Standard") { if (blnDoFullHouse) { strHeroLabSettingsName = objCache.BuildMethod == CharacterBuildMethod.Karma ? "Full House (Point Buy)" : "Full House"; } else if (objCache.BuildMethod == CharacterBuildMethod.Karma) { strHeroLabSettingsName = "Point Buy"; } } objCache.SettingsName = strHeroLabSettingsName; } objCache.Created = objCache.Karma != "0"; if (!objCache.Created) { XPathNodeIterator xmlJournalEntries = await xmlBaseCharacterNode.SelectAndCacheExpressionAsync("journals/journal"); if (xmlJournalEntries?.Count > 1) { objCache.Created = true; } else if (xmlJournalEntries?.Count == 1 && xmlJournalEntries.Current?.SelectSingleNode("@name")?.Value != "Title") { objCache.Created = true; } } string strImageString = xmlBaseCharacterNode.SelectSingleNode("images/image/@filename")?.Value; if (!string.IsNullOrEmpty(strImageString)) { (bool blnSuccess, Bitmap objTemp) = await _dicImages.TryGetValueAsync(strImageString); if (blnSuccess) { objCache.Mugshot = objTemp; } } objCache.FilePath = strFile; TreeNode objNode = new TreeNode { Text = await CalculatedName(objCache), ToolTipText = await strFile.CheapReplaceAsync(Utils.GetStartupPath, () => '<' + Application.ProductName + '>') }; nodRootNode.Nodes.Add(objNode); await _lstCharacterCache.AddAsync(objCache); objNode.Tag = await _lstCharacterCache.IndexOfAsync(objCache); } } nodRootNode.Expand(); return(nodRootNode); } finally { await lstCharacterXmlStatblocks.DisposeAsync(); } }
private async Task DoXsltUpdate(CancellationToken token = default) { token.ThrowIfCancellationRequested(); if (!_blnLoading) { if (_objCharacterXml != null) { _strXslt = await cboXSLT.DoThreadSafeFuncAsync(x => x.SelectedValue?.ToString(), token); if (!string.IsNullOrEmpty(_strXslt)) { CursorWait objCursorWait = await CursorWait.NewAsync(this, token : token); try { token.ThrowIfCancellationRequested(); string strText = await LanguageManager.GetStringAsync("String_Generating_Data"); await txtText.DoThreadSafeAsync(x => x.Text = strText, token); (bool blnSuccess, Tuple <string, string> strBoxText) = await _dicCache.TryGetValueAsync( new Tuple <string, string>(_strExportLanguage, _strXslt), token); token.ThrowIfCancellationRequested(); if (blnSuccess) { await txtText.DoThreadSafeAsync(x => x.Text = strBoxText.Item2, token); } else { CancellationTokenSource objNewSource = new CancellationTokenSource(); CancellationTokenSource objTemp = Interlocked.Exchange(ref _objXmlGeneratorCancellationTokenSource, objNewSource); if (objTemp?.IsCancellationRequested == false) { objTemp.Cancel(false); objTemp.Dispose(); } try { token.ThrowIfCancellationRequested(); } catch (OperationCanceledException) { Interlocked.CompareExchange(ref _objXmlGeneratorCancellationTokenSource, null, objNewSource); objNewSource.Dispose(); throw; } try { if (_tskXmlGenerator?.IsCompleted == false) { await _tskXmlGenerator; } } catch (OperationCanceledException) { // Swallow this } CancellationToken objToken = objNewSource.Token; _tskXmlGenerator = _strXslt == "JSON" ? Task.Run(() => GenerateJson(objToken), objToken) : Task.Run(() => GenerateXml(objToken), objToken); } } finally { await objCursorWait.DisposeAsync(); } } } else { token.ThrowIfCancellationRequested(); CancellationTokenSource objNewSource = new CancellationTokenSource(); CancellationTokenSource objTemp = Interlocked.Exchange(ref _objCharacterXmlGeneratorCancellationTokenSource, objNewSource); if (objTemp?.IsCancellationRequested == false) { objTemp.Cancel(false); objTemp.Dispose(); } try { token.ThrowIfCancellationRequested(); } catch (OperationCanceledException) { Interlocked.CompareExchange(ref _objCharacterXmlGeneratorCancellationTokenSource, null, objNewSource); objNewSource.Dispose(); throw; } try { if (_tskCharacterXmlGenerator?.IsCompleted == false) { await _tskCharacterXmlGenerator; } } catch (OperationCanceledException) { // Swallow this } CancellationToken objToken = objNewSource.Token; _tskCharacterXmlGenerator = Task.Run(() => GenerateCharacterXml(objToken), objToken); } } }
private async ValueTask DoXsltUpdate() { if (!_blnLoading) { if (_objCharacterXml != null) { _strXslt = cboXSLT.SelectedValue?.ToString(); if (!string.IsNullOrEmpty(_strXslt)) { using (CursorWait.New(this)) { await txtText.DoThreadSafeAsync( async x => x.Text = await LanguageManager.GetStringAsync("String_Generating_Data")); (bool blnSuccess, Tuple <string, string> strBoxText) = await _dicCache.TryGetValueAsync( new Tuple <string, string>(_strExportLanguage, _strXslt)); if (blnSuccess) { await txtText.DoThreadSafeAsync(x => x.Text = strBoxText.Item2); } else { if (_objXmlGeneratorCancellationTokenSource != null) { _objXmlGeneratorCancellationTokenSource.Cancel(false); _objXmlGeneratorCancellationTokenSource.Dispose(); } _objXmlGeneratorCancellationTokenSource = new CancellationTokenSource(); try { if (_tskXmlGenerator?.IsCompleted == false) { await _tskXmlGenerator; } } catch (TaskCanceledException) { // Swallow this } _tskXmlGenerator = _strXslt == "JSON" ? Task.Run(GenerateJson, _objXmlGeneratorCancellationTokenSource.Token) : Task.Run(GenerateXml, _objXmlGeneratorCancellationTokenSource.Token); } } } } else { if (_objCharacterXmlGeneratorCancellationTokenSource != null) { _objCharacterXmlGeneratorCancellationTokenSource.Cancel(false); _objCharacterXmlGeneratorCancellationTokenSource.Dispose(); } _objCharacterXmlGeneratorCancellationTokenSource = new CancellationTokenSource(); try { if (_tskCharacterXmlGenerator?.IsCompleted == false) { await _tskCharacterXmlGenerator; } } catch (TaskCanceledException) { // Swallow this } _tskCharacterXmlGenerator = Task.Run(GenerateCharacterXml, _objCharacterXmlGeneratorCancellationTokenSource.Token); } } }
private async void lstItems_SelectedIndexChanged(object sender, EventArgs e) { if (_blnSkipRefresh) { return; } try { using (await CursorWait.NewAsync(this, token: _objGenericToken)) { if (await lstItems.DoThreadSafeFuncAsync(x => x.SelectedValue, _objGenericToken) is MasterIndexEntry objEntry) { await Task.WhenAll( lblSourceLabel.DoThreadSafeAsync(x => x.Visible = true, _objGenericToken), lblSourceClickReminder.DoThreadSafeAsync(x => x.Visible = true, _objGenericToken), objEntry.DisplaySource.SetControlAsync(lblSource, _objGenericToken)); (bool blnSuccess, Task <string> tskNotes) = await _dicCachedNotes.TryGetValueAsync(objEntry, _objGenericToken); if (!blnSuccess) { if (!GlobalSettings.Language.Equals(GlobalSettings.DefaultLanguage, StringComparison.OrdinalIgnoreCase) && (objEntry.TranslatedNameOnPage != objEntry.EnglishNameOnPage || objEntry.Source.Page != objEntry.DisplaySource.Page)) { // don't check again it is not translated tskNotes = Task.Run(async() => { string strReturn = await CommonFunctions.GetTextFromPdfAsync( objEntry.Source.ToString(), objEntry.EnglishNameOnPage); if (string.IsNullOrEmpty(strReturn)) { strReturn = await CommonFunctions.GetTextFromPdfAsync( objEntry.DisplaySource.ToString(), objEntry.TranslatedNameOnPage); } return(strReturn); }, _objGenericToken); } else { tskNotes = Task.Run(() => CommonFunctions.GetTextFromPdfAsync( objEntry.Source.ToString(), objEntry.EnglishNameOnPage), _objGenericToken); } await _dicCachedNotes.TryAddAsync(objEntry, tskNotes, _objGenericToken); } string strNotes = await tskNotes; await txtNotes.DoThreadSafeAsync(x => { x.Text = strNotes; x.Visible = true; }, _objGenericToken); } else { await Task.WhenAll( lblSourceLabel.DoThreadSafeAsync(x => x.Visible = false, _objGenericToken), lblSourceClickReminder.DoThreadSafeAsync(x => x.Visible = false, _objGenericToken), SourceString.Blank.SetControlAsync(lblSource, _objGenericToken), txtNotes.DoThreadSafeAsync(x => x.Visible = false, _objGenericToken)); } } } catch (OperationCanceledException) { //swallow this } }
public async ValueTask <string> Macro(string innerText, XPathNavigator xmlBaseMacrosNode) { if (string.IsNullOrEmpty(innerText)) { return(string.Empty); } string endString = innerText.ToLowerInvariant().Substring(1).TrimEnd(',', '.'); string macroName, macroPool; if (endString.Contains('_')) { string[] split = endString.Split('_'); macroName = split[0]; macroPool = split[1]; } else { macroName = macroPool = endString; } switch (macroName) { //$DOLLAR is defined elsewhere to prevent recursive calling case "street": return(!string.IsNullOrEmpty(_objCharacter.Alias) ? _objCharacter.Alias : "Alias "); case "real": return(!string.IsNullOrEmpty(_objCharacter.Name) ? _objCharacter.Name : "Unnamed John Doe "); case "year" when int.TryParse(_objCharacter.Age, out int year): return(int.TryParse(macroPool, out int age) ? (DateTime.UtcNow.Year + 62 + age - year).ToString(GlobalSettings.CultureInfo) : (DateTime.UtcNow.Year + 62 - year).ToString(GlobalSettings.CultureInfo)); case "year": return("(ERROR PARSING \"" + _objCharacter.Age + "\")"); } //Did not meet predefined macros, check user defined XPathNavigator xmlUserMacroNode = xmlBaseMacrosNode?.SelectSingleNode(macroName); if (xmlUserMacroNode != null) { XPathNavigator xmlUserMacroFirstChild = xmlUserMacroNode.SelectChildren(XPathNodeType.Element).Current; if (xmlUserMacroFirstChild != null) { //Already defined, no need to do anything fancy (bool blnSuccess, string strSelectedNodeName) = await _dicPersistence.TryGetValueAsync(macroPool); if (!blnSuccess) { switch (xmlUserMacroFirstChild.Name) { case "random": { XPathNodeIterator xmlPossibleNodeList = await xmlUserMacroFirstChild.SelectAndCacheExpressionAsync("./*[not(self::default)]"); if (xmlPossibleNodeList.Count > 0) { int intUseIndex = xmlPossibleNodeList.Count > 1 ? await GlobalSettings.RandomGenerator.NextModuloBiasRemovedAsync(xmlPossibleNodeList.Count) : 0; int i = 0; foreach (XPathNavigator xmlLoopNode in xmlPossibleNodeList) { if (i == intUseIndex) { strSelectedNodeName = xmlLoopNode.Name; break; } ++i; } } break; } case "persistent": { //Any node not named XPathNodeIterator xmlPossibleNodeList = await xmlUserMacroFirstChild.SelectAndCacheExpressionAsync("./*[not(self::default)]"); if (xmlPossibleNodeList.Count > 0) { int intUseIndex = xmlPossibleNodeList.Count > 1 ? await GlobalSettings.RandomGenerator.NextModuloBiasRemovedAsync(xmlPossibleNodeList.Count) : 0; int i = 0; foreach (XPathNavigator xmlLoopNode in xmlPossibleNodeList) { if (i == intUseIndex) { strSelectedNodeName = xmlLoopNode.Name; break; } ++i; } if (!await _dicPersistence.TryAddAsync(macroPool, strSelectedNodeName)) { strSelectedNodeName = (await _dicPersistence.TryGetValueAsync(macroPool)).Item2; } } break; } default: return("(Formating error in $DOLLAR" + macroName + ')'); } } if (!string.IsNullOrEmpty(strSelectedNodeName)) { string strSelected = xmlUserMacroFirstChild.SelectSingleNode(strSelectedNodeName)?.Value; if (!string.IsNullOrEmpty(strSelected)) { return(strSelected); } } string strDefault = (await xmlUserMacroFirstChild.SelectSingleNodeAndCacheExpressionAsync("default"))?.Value; if (!string.IsNullOrEmpty(strDefault)) { return(strDefault); } return("(Unknown key " + macroPool + " in $DOLLAR" + macroName + ')'); } return(xmlUserMacroNode.Value); } return("(Unknown Macro $DOLLAR" + innerText.Substring(1) + ')'); }
private async void lstItems_SelectedIndexChanged(object sender, EventArgs e) { if (_blnSkipRefresh) { return; } using (CursorWait.New(this)) { if (lstItems.DoThreadSafeFunc(x => x.SelectedValue) is MasterIndexEntry objEntry) { await lblSourceLabel.DoThreadSafeAsync(x => x.Visible = true); await lblSource.DoThreadSafeAsync(x => x.Visible = true); await lblSourceClickReminder.DoThreadSafeAsync(x => x.Visible = true); await lblSource.DoThreadSafeAsync(x => x.Text = objEntry.DisplaySource.ToString()); await lblSource.DoThreadSafeAsync(x => x.ToolTipText = objEntry.DisplaySource.LanguageBookTooltip); (bool blnSuccess, Task <string> tskNotes) = await _dicCachedNotes.TryGetValueAsync(objEntry); if (!blnSuccess) { if (!GlobalSettings.Language.Equals(GlobalSettings.DefaultLanguage, StringComparison.OrdinalIgnoreCase) && (objEntry.TranslatedNameOnPage != objEntry.EnglishNameOnPage || objEntry.Source.Page != objEntry.DisplaySource.Page)) { // don't check again it is not translated tskNotes = Task.Run(async() => { string strReturn = await CommonFunctions.GetTextFromPdfAsync(objEntry.Source.ToString(), objEntry.EnglishNameOnPage); if (string.IsNullOrEmpty(strReturn)) { strReturn = await CommonFunctions.GetTextFromPdfAsync( objEntry.DisplaySource.ToString(), objEntry.TranslatedNameOnPage); } return(strReturn); }); } else { tskNotes = Task.Run(() => CommonFunctions.GetTextFromPdfAsync(objEntry.Source.ToString(), objEntry.EnglishNameOnPage)); } await _dicCachedNotes.TryAddAsync(objEntry, tskNotes); } string strNotes = await tskNotes; await txtNotes.DoThreadSafeAsync(x => x.Text = strNotes); await txtNotes.DoThreadSafeAsync(x => x.Visible = true); } else { await lblSourceLabel.DoThreadSafeAsync(x => x.Visible = false); await lblSource.DoThreadSafeAsync(x => x.Visible = false); await lblSourceClickReminder.DoThreadSafeAsync(x => x.Visible = false); await txtNotes.DoThreadSafeAsync(x => x.Visible = false); } } }