private static void AddSpecificCustomCharacterSetting(string strSettingName) { if (_intDicLoadedCharacterSettingsLoadedStatus <= 1) { return; } CharacterSettings objNewCharacterSettings = new CharacterSettings(); if (!objNewCharacterSettings.Load(strSettingName, false) || (objNewCharacterSettings.BuildMethodIsLifeModule && !GlobalSettings.LifeModuleEnabled)) { objNewCharacterSettings.Dispose(); return; } while (true) { if (s_DicLoadedCharacterSettings.TryAdd(objNewCharacterSettings.DictionaryKey, objNewCharacterSettings)) { return; } // We somehow already have a setting loaded with this name, so just copy over the values and dispose of the new setting instead if (s_DicLoadedCharacterSettings.TryGetValue(objNewCharacterSettings.DictionaryKey, out CharacterSettings objOldCharacterSettings)) { objOldCharacterSettings.CopyValues(objNewCharacterSettings); objNewCharacterSettings.Dispose(); return; } } }
/// <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 bool AddTaggedCollectionChanged(object objTag, NotifyCollectionChangedEventHandler funcDelegateToAdd) { if (!_dicTaggedAddedDelegates.TryGetValue(objTag, out HashSet <NotifyCollectionChangedEventHandler> setFuncs)) { setFuncs = new HashSet <NotifyCollectionChangedEventHandler>(); _dicTaggedAddedDelegates.Add(objTag, setFuncs); } if (setFuncs.Add(funcDelegateToAdd)) { base.CollectionChanged += funcDelegateToAdd; return(true); } 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. /// </summary> /// <param name="strXslFilePath">Absolute path to the Xsl file to be transformed.</param> /// <returns>The compiled Xsl transform of <paramref name="strXslFilePath"/>.</returns> public static XslCompiledTransform GetTransformForFile(string strXslFilePath) { if (!File.Exists(strXslFilePath)) { throw new FileNotFoundException(nameof(strXslFilePath)); } DateTime datLastWriteTimeUtc = File.GetLastWriteTimeUtc(strXslFilePath); XslCompiledTransform objReturn; if (!s_dicCompiledTransforms.TryGetValue( strXslFilePath, out Tuple <DateTime, XslCompiledTransform> tupCachedData) || tupCachedData.Item1 <= datLastWriteTimeUtc) { #if DEBUG objReturn = new XslCompiledTransform(true); #else objReturn = new XslCompiledTransform(); #endif objReturn.Load(strXslFilePath); s_dicCompiledTransforms.Remove(strXslFilePath); s_dicCompiledTransforms.TryAdd( strXslFilePath, new Tuple <DateTime, XslCompiledTransform>(datLastWriteTimeUtc, objReturn)); } else { objReturn = tupCachedData.Item2; } return(objReturn); }
public static TimeSpan Finish(string taskname) { TimeSpan final = TimeSpan.Zero; if (s_DictionaryStarts.TryRemove(taskname, out TimeSpan objStartTimeSpan)) { final = s_Time.Elapsed - objStartTimeSpan; #if DEBUG string strLogEntry = string.Format(GlobalSettings.InvariantCultureInfo, "Task \"{0}\" finished in {1}", taskname, final); //Log.Trace(strLogEntry); Debug.WriteLine(strLogEntry); #endif if (s_DictionaryStatistics.TryGetValue(taskname, out Tuple <TimeSpan, int> existing)) { s_DictionaryStatistics[taskname] = new Tuple <TimeSpan, int>(existing.Item1 + final, existing.Item2 + 1); } else { s_DictionaryStatistics.TryAdd(taskname, new Tuple <TimeSpan, int>(final, 1)); } } else { Debug.WriteLine("Non started task \"" + taskname + "\" finished"); } return(final); }
public static TimeSpan Elapsed(string taskname) { if (s_DictionaryStarts.TryGetValue(taskname, out TimeSpan objStartTimeSpan)) { return(s_Time.Elapsed - objStartTimeSpan); } return(TimeSpan.Zero); }
/// <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); }
private void lstItems_SelectedIndexChanged(object sender, EventArgs e) { if (_blnSkipRefresh) { return; } using (new CursorWait(this)) { if (lstItems.SelectedValue is MasterIndexEntry objEntry) { lblSourceLabel.Visible = true; lblSource.Visible = true; lblSourceClickReminder.Visible = true; lblSource.Text = objEntry.DisplaySource.ToString(); lblSource.ToolTipText = objEntry.DisplaySource.LanguageBookTooltip; if (!_dicCachedNotes.TryGetValue(objEntry, out string strNotes)) { strNotes = CommonFunctions.GetTextFromPdf(objEntry.Source.ToString(), objEntry.EnglishNameOnPage); if (string.IsNullOrEmpty(strNotes) && !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 strNotes = CommonFunctions.GetTextFromPdf(objEntry.DisplaySource.ToString(), objEntry.TranslatedNameOnPage); } _dicCachedNotes.TryAdd(objEntry, strNotes); } txtNotes.Text = strNotes; txtNotes.Visible = true; } else { lblSourceLabel.Visible = false; lblSource.Visible = false; lblSourceClickReminder.Visible = false; txtNotes.Visible = false; } } }
public CursorWait(Control objControl = null, bool blnAppStarting = false) { if (objControl.IsNullOrDisposed()) { _objControl = null; lock (s_ObjApplicationWaitCursorsLock) { ++_intApplicationWaitCursors; if (_intApplicationWaitCursors > 0) { Application.UseWaitCursor = true; } } return; } _objTimer.Start(); Log.Trace("CursorWait for Control \"" + objControl + "\" started with Guid \"" + _guidInstance + "\"."); _objControl = objControl; Form frmControl = _objControl as Form; CursorToUse = blnAppStarting ? Cursors.AppStarting : Cursors.WaitCursor; if (frmControl?.IsMdiChild != false) { if (frmControl != null) { _frmControlTopParent = frmControl.MdiParent; } else if (_objControl is UserControl objUserControl) { _frmControlTopParent = objUserControl.ParentForm; } else { for (Control objLoop = _objControl?.Parent; objLoop != null; objLoop = objLoop.Parent) { if (objLoop is Form objLoopForm) { _frmControlTopParent = objLoopForm; break; } } } } ThreadSafeList <CursorWait> lstNew = new ThreadSafeList <CursorWait>(1); while (_objControl != null && !s_DicWaitingControls.TryAdd(_objControl, lstNew)) { if (!s_DicWaitingControls.TryGetValue(_objControl, out ThreadSafeList <CursorWait> lstExisting)) { continue; } lstNew.Dispose(); CursorWait objLastCursorWait = null; // Need this pattern because the size of lstExisting might change in between fetching lstExisting.Count and lstExisting[] bool blnDoLoop = true; while (blnDoLoop) { blnDoLoop = false; int intIndex = lstExisting.Count - 1; if (intIndex >= 0) { try { objLastCursorWait = lstExisting[intIndex]; } catch (ArgumentOutOfRangeException) { blnDoLoop = true; } } } lstExisting.Add(this); if (blnAppStarting) { if (objLastCursorWait == null) { SetControlCursor(CursorToUse); } else if (objLastCursorWait.CursorToUse == Cursors.WaitCursor) { CursorToUse = Cursors.WaitCursor; } } else if (objLastCursorWait == null || objLastCursorWait.CursorToUse == Cursors.AppStarting) { SetControlCursor(CursorToUse); } return; } // Here for safety purposes if (_objControl.IsNullOrDisposed()) { _objControl = null; _frmControlTopParent = null; lock (s_ObjApplicationWaitCursorsLock) { ++_intApplicationWaitCursors; if (_intApplicationWaitCursors > 0) { Application.UseWaitCursor = true; } } return; } lstNew.Add(this); SetControlCursor(CursorToUse); }
private async ValueTask DoXsltUpdate() { if (!_blnLoading) { if (_objCharacterXml != null) { _strXslt = cboXSLT.Text; if (!string.IsNullOrEmpty(_strXslt)) { using (new CursorWait(this)) { await txtText.DoThreadSafeAsync( () => txtText.Text = LanguageManager.GetString("String_Generating_Data")); if (_dicCache.TryGetValue(new Tuple <string, string>(_strExportLanguage, _strXslt), out Tuple <string, string> strBoxText)) { await txtText.DoThreadSafeAsync(() => txtText.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 == "Export 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); } } }
/// <summary> /// Generates a character cache, which prevents us from repeatedly loading XmlNodes or caching a full character. /// </summary> /// <param name="strFile"></param> private TreeNode CacheCharacters(string strFile) { if (!File.Exists(strFile)) { Program.MainForm.ShowMessageBox( this, string.Format(GlobalSettings.CultureInfo, LanguageManager.GetString("Message_File_Cannot_Be_Accessed"), strFile)); return(null); } using (ThreadSafeList <XPathNavigator> lstCharacterXmlStatblocks = new ThreadSafeList <XPathNavigator>(3)) { try { using (ZipArchive zipArchive = ZipFile.Open(strFile, ZipArchiveMode.Read, Encoding.GetEncoding(850))) { Parallel.ForEach(zipArchive.Entries, entry => { 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 { XPathDocument xmlSourceDoc; using (StreamReader sr = new StreamReader(entry.Open(), true)) using (XmlReader objXmlReader = XmlReader.Create(sr, GlobalSettings.SafeXmlReaderSettings)) xmlSourceDoc = new XPathDocument(objXmlReader); XPathNavigator objToAdd = xmlSourceDoc.CreateNavigator(); // ReSharper disable once AccessToDisposedClosure 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 (!_dicImages.TryAdd(strKey, bmpNewMugshot)) { if (_dicImages.TryRemove(strKey, out Bitmap bmpOldMugshot)) { bmpOldMugshot?.Dispose(); } } } } }); } } catch (IOException) { Program.MainForm.ShowMessageBox( this, string.Format(GlobalSettings.CultureInfo, LanguageManager.GetString("Message_File_Cannot_Be_Accessed"), strFile)); return(null); } catch (NotSupportedException) { Program.MainForm.ShowMessageBox( this, string.Format(GlobalSettings.CultureInfo, LanguageManager.GetString("Message_File_Cannot_Be_Accessed"), strFile)); return(null); } catch (UnauthorizedAccessException) { Program.MainForm.ShowMessageBox( this, LanguageManager.GetString("Message_Insufficient_Permissions_Warning")); return(null); } string strFileText = strFile.CheapReplace(Utils.GetStartupPath, () => '<' + Application.ProductName + '>'); TreeNode nodRootNode = new TreeNode { Text = strFileText, ToolTipText = strFileText }; XPathNavigator xmlMetatypesDocument = XmlManager.LoadXPath("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 xmlMetatype.SelectAndCacheExpression("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")?.Value == "25" ? nameof(CharacterBuildMethod.Priority) : nameof(CharacterBuildMethod.Karma); objCache.Created = objCache.Karma != "0"; if (!objCache.Created) { XPathNodeIterator xmlJournalEntries = xmlBaseCharacterNode.SelectAndCacheExpression("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) && _dicImages.TryGetValue(strImageString, out Bitmap objTemp)) { objCache.Mugshot = objTemp; } objCache.FilePath = strFile; TreeNode objNode = new TreeNode { Text = CalculatedName(objCache), ToolTipText = strFile.CheapReplace(Utils.GetStartupPath, () => '<' + Application.ProductName + '>') }; nodRootNode.Nodes.Add(objNode); _lstCharacterCache.Add(objCache); objNode.Tag = _lstCharacterCache.IndexOf(objCache); } } nodRootNode.Expand(); return(nodRootNode); } }