private static void LoadCharacterSettings() { _intDicLoadedCharacterSettingsLoadedStatus = 0; try { s_DicLoadedCharacterSettings.Clear(); if (Utils.IsDesignerMode || Utils.IsRunningInVisualStudio) { CharacterSettings objNewCharacterSettings = new CharacterSettings(); if (!s_DicLoadedCharacterSettings.TryAdd(GlobalSettings.DefaultCharacterSetting, objNewCharacterSettings)) { objNewCharacterSettings.Dispose(); } return; } IEnumerable <XPathNavigator> xmlSettingsIterator = XmlManager.LoadXPath("settings.xml") .SelectAndCacheExpression("/chummer/settings/setting").Cast <XPathNavigator>(); Parallel.ForEach(xmlSettingsIterator, xmlBuiltInSetting => { CharacterSettings objNewCharacterSettings = new CharacterSettings(); if (!objNewCharacterSettings.Load(xmlBuiltInSetting) || (objNewCharacterSettings.BuildMethodIsLifeModule && !GlobalSettings.LifeModuleEnabled) || !s_DicLoadedCharacterSettings.TryAdd(objNewCharacterSettings.DictionaryKey, objNewCharacterSettings)) { objNewCharacterSettings.Dispose(); } }); string strSettingsPath = Path.Combine(Utils.GetStartupPath, "settings"); if (Directory.Exists(strSettingsPath)) { Parallel.ForEach(Directory.EnumerateFiles(strSettingsPath, "*.xml"), strSettingsFilePath => { string strSettingName = Path.GetFileName(strSettingsFilePath); CharacterSettings objNewCharacterSettings = new CharacterSettings(); if (!objNewCharacterSettings.Load(strSettingName, false) || (objNewCharacterSettings.BuildMethodIsLifeModule && !GlobalSettings.LifeModuleEnabled) || !s_DicLoadedCharacterSettings.TryAdd(objNewCharacterSettings.DictionaryKey, objNewCharacterSettings)) { objNewCharacterSettings.Dispose(); } }); } } finally { _intDicLoadedCharacterSettingsLoadedStatus = 1; } }
private async ValueTask LoadContent() { using (CustomActivity opLoadMasterindex = Timekeeper.StartSyncron("op_load_frm_masterindex", null, CustomActivity.OperationType.RequestOperation, null)) { _dicCachedNotes.Clear(); foreach (MasterIndexEntry objExistingEntry in _lstItems.Select(x => x.Value)) { objExistingEntry.Dispose(); } _lstItems.Clear(); _lstFileNamesWithItems.Clear(); string strSourceFilter; using (new FetchSafelyFromPool <HashSet <string> >(Utils.StringHashSetPool, out HashSet <string> setValidCodes)) { foreach (XPathNavigator xmlBookNode in (await XmlManager.LoadXPathAsync( "books.xml", _objSelectedSetting.EnabledCustomDataDirectoryPaths)) .SelectAndCacheExpression("/chummer/books/book/code")) { setValidCodes.Add(xmlBookNode.Value); } setValidCodes.IntersectWith(_objSelectedSetting.Books); strSourceFilter = setValidCodes.Count > 0 ? '(' + string.Join(" or ", setValidCodes.Select(x => "source = " + x.CleanXPath())) + ')' : "source"; } using (_ = Timekeeper.StartSyncron("load_frm_masterindex_load_andpopulate_entries", opLoadMasterindex)) { ConcurrentBag <ListItem> lstItemsForLoading = new ConcurrentBag <ListItem>(); using (_ = Timekeeper.StartSyncron("load_frm_masterindex_load_entries", opLoadMasterindex)) { ConcurrentBag <ListItem> lstFileNamesWithItemsForLoading = new ConcurrentBag <ListItem>(); // Prevents locking the UI thread while still benefitting from static scheduling of Parallel.ForEach await Task.WhenAll(_astrFileNames.Select(strFileName => Task.Run(async() => { XPathNavigator xmlBaseNode = await XmlManager.LoadXPathAsync(strFileName, _objSelectedSetting.EnabledCustomDataDirectoryPaths); xmlBaseNode = xmlBaseNode.SelectSingleNodeAndCacheExpression("/chummer"); if (xmlBaseNode == null) { return; } bool blnLoopFileNameHasItems = false; foreach (XPathNavigator xmlItemNode in xmlBaseNode.SelectAndCacheExpression( ".//*[page and " + strSourceFilter + ']')) { blnLoopFileNameHasItems = true; string strName = xmlItemNode.SelectSingleNodeAndCacheExpression("name")?.Value; string strDisplayName = xmlItemNode.SelectSingleNodeAndCacheExpression("translate")?.Value ?? strName ?? xmlItemNode.SelectSingleNodeAndCacheExpression("id")?.Value ?? await LanguageManager.GetStringAsync("String_Unknown"); string strSource = xmlItemNode.SelectSingleNodeAndCacheExpression("source")?.Value; string strPage = xmlItemNode.SelectSingleNodeAndCacheExpression("page")?.Value; string strDisplayPage = xmlItemNode.SelectSingleNodeAndCacheExpression("altpage")?.Value ?? strPage; string strEnglishNameOnPage = xmlItemNode.SelectSingleNodeAndCacheExpression("nameonpage")?.Value ?? strName; string strTranslatedNameOnPage = xmlItemNode.SelectSingleNodeAndCacheExpression("altnameonpage")?.Value ?? strDisplayName; string strNotes = xmlItemNode.SelectSingleNodeAndCacheExpression("altnotes")?.Value ?? xmlItemNode.SelectSingleNodeAndCacheExpression("notes")?.Value; MasterIndexEntry objEntry = new MasterIndexEntry( strDisplayName, strFileName, new SourceString(strSource, strPage, GlobalSettings.DefaultLanguage, GlobalSettings.InvariantCultureInfo), new SourceString(strSource, strDisplayPage, GlobalSettings.Language, GlobalSettings.CultureInfo), strEnglishNameOnPage, strTranslatedNameOnPage); lstItemsForLoading.Add(new ListItem(objEntry, strDisplayName)); if (!string.IsNullOrEmpty(strNotes)) { _dicCachedNotes.TryAdd(objEntry, strNotes); } } if (blnLoopFileNameHasItems) { lstFileNamesWithItemsForLoading.Add(new ListItem(strFileName, strFileName)); } }))); _lstFileNamesWithItems.AddRange(lstFileNamesWithItemsForLoading); } using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_entries", opLoadMasterindex)) { string strSpace = await LanguageManager.GetStringAsync("String_Space"); string strFormat = "{0}" + strSpace + "[{1}]"; Dictionary <string, List <ListItem> > dicHelper = new Dictionary <string, List <ListItem> >(lstItemsForLoading.Count); try { foreach (ListItem objItem in lstItemsForLoading) { if (!(objItem.Value is MasterIndexEntry objEntry)) { continue; } string strKey = objEntry.DisplayName.ToUpperInvariant(); if (dicHelper.TryGetValue(strKey, out List <ListItem> lstExistingItems)) { ListItem objExistingItem = lstExistingItems.Find( x => x.Value is MasterIndexEntry y && objEntry.DisplaySource.Equals(y.DisplaySource)); if (objExistingItem.Value is MasterIndexEntry objLoopEntry) { objLoopEntry.FileNames.UnionWith(objEntry.FileNames); objEntry.Dispose(); } else { using (new FetchSafelyFromPool <List <ListItem> >( Utils.ListItemListPool, out List <ListItem> lstItemsNeedingNameChanges)) { lstItemsNeedingNameChanges.AddRange(lstExistingItems.FindAll( x => x.Value is MasterIndexEntry y && !objEntry.FileNames.IsSubsetOf(y.FileNames))); if (lstItemsNeedingNameChanges.Count == 0) { _lstItems.Add( objItem); // Not using AddRange because of potential memory issues lstExistingItems.Add(objItem); } else { ListItem objItemToAdd = new ListItem( objItem.Value, string.Format(GlobalSettings.CultureInfo, strFormat, objItem.Name, string.Join( ',' + strSpace, objEntry.FileNames))); _lstItems.Add( objItemToAdd); // Not using AddRange because of potential memory issues lstExistingItems.Add(objItemToAdd); foreach (ListItem objToRename in lstItemsNeedingNameChanges) { _lstItems.Remove(objToRename); lstExistingItems.Remove(objToRename); if (!(objToRename.Value is MasterIndexEntry objExistingEntry)) { continue; } objItemToAdd = new ListItem(objToRename.Value, string.Format( GlobalSettings.CultureInfo, strFormat, objExistingEntry.DisplayName, string.Join( ',' + strSpace, objExistingEntry.FileNames))); _lstItems.Add( objItemToAdd); // Not using AddRange because of potential memory issues lstExistingItems.Add(objItemToAdd); } } } } } else { _lstItems.Add(objItem); // Not using AddRange because of potential memory issues List <ListItem> lstHelperItems = Utils.ListItemListPool.Get(); lstHelperItems.Add(objItem); dicHelper.Add(strKey, lstHelperItems); } } } finally { foreach (List <ListItem> lstHelperItems in dicHelper.Values) { Utils.ListItemListPool.Return(lstHelperItems); } } } } using (_ = Timekeeper.StartSyncron("load_frm_masterindex_sort_entries", opLoadMasterindex)) { _lstItems.Sort(CompareListItems.CompareNames); _lstFileNamesWithItems.Sort(CompareListItems.CompareNames); } using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_controls", opLoadMasterindex)) { _lstFileNamesWithItems.Insert(0, new ListItem(string.Empty, await LanguageManager.GetStringAsync("String_All"))); int intOldSelectedIndex = cboFile.SelectedIndex; cboFile.BeginUpdate(); cboFile.PopulateWithListItems(_lstFileNamesWithItems); try { cboFile.SelectedIndex = Math.Max(intOldSelectedIndex, 0); } // For some reason, some unit tests will fire this exception even when _lstFileNamesWithItems is explicitly checked for having enough items catch (ArgumentOutOfRangeException) { cboFile.SelectedIndex = -1; } cboFile.EndUpdate(); lstItems.BeginUpdate(); lstItems.PopulateWithListItems(_lstItems); lstItems.SelectedIndex = -1; lstItems.EndUpdate(); _blnSkipRefresh = false; } } }