public static void ContainsTests() { string[] anArray = new string[] { "one", "two", "three", "four", "five" }; ReadOnlyObservableCollection <string> readOnlyCol = new ReadOnlyObservableCollection <string>(new ObservableCollection <string>(anArray)); for (int i = 0; i < anArray.Length; i++) { string item = anArray[i]; Assert.True(readOnlyCol.Contains(item), "ReadOnlyCol did not contain item: " + anArray[i] + " at index: " + i); } Assert.False(readOnlyCol.Contains("randomItem"), "ReadOnlyCol should not have contained non-existent item"); Assert.False(readOnlyCol.Contains(null), "ReadOnlyCol should not have contained null"); }
private void LoadCharacters(bool blnRefreshFavorites = true, bool blnRefreshRecents = true, bool blnRefreshWatch = true) { ReadOnlyObservableCollection <string> lstFavorites = new ReadOnlyObservableCollection <string>(GlobalOptions.FavoritedCharacters); bool blnAddFavouriteNode = false; TreeNode objFavouriteNode = null; TreeNode[] lstFavoritesNodes = null; if (blnRefreshFavorites) { objFavouriteNode = treCharacterList.FindNode("Favourite", false); if (objFavouriteNode == null) { objFavouriteNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_FavouriteCharacters", GlobalOptions.Language)) { Tag = "Favourite" }; blnAddFavouriteNode = true; } lstFavoritesNodes = new TreeNode[lstFavorites.Count]; } IList <string> lstRecents = new List <string>(GlobalOptions.MostRecentlyUsedCharacters); List <string> lstWatch = new List <string>(); if (!string.IsNullOrEmpty(GlobalOptions.CharacterRosterPath) && Directory.Exists(GlobalOptions.CharacterRosterPath)) { string[] objFiles = Directory.GetFiles(GlobalOptions.CharacterRosterPath, "*.chum5"); for (int i = 0; i < objFiles.Length; ++i) { string strFile = objFiles[i]; // Make sure we're not loading a character that was already loaded by the MRU list. if (lstFavorites.Contains(strFile) || lstRecents.Contains(strFile)) { continue; } lstWatch.Add(strFile); } } bool blnAddWatchNode = false; TreeNode objWatchNode = null; TreeNode[] lstWatchNodes = null; if (blnRefreshWatch) { objWatchNode = treCharacterList.FindNode("Watch", false); if (objWatchNode == null && lstWatch.Count > 0) { objWatchNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_WatchFolder", GlobalOptions.Language)) { Tag = "Watch" }; blnAddWatchNode = true; } lstWatchNodes = new TreeNode[lstWatch.Count]; } bool blnAddRecentNode = false; TreeNode objRecentNode = null; TreeNode[] lstRecentsNodes = null; if (blnRefreshRecents) { // Add any characters that are open to the displayed list so we can have more than 10 characters listed foreach (CharacterShared objCharacterForm in Program.MainForm.OpenCharacterForms) { string strFile = objCharacterForm.CharacterObject.FileName; // Make sure we're not loading a character that was already loaded by the MRU list. if (lstFavorites.Contains(strFile) || lstRecents.Contains(strFile) || lstWatch.Contains(strFile)) { continue; } lstRecents.Add(strFile); } foreach (string strFavorite in lstFavorites) { lstRecents.Remove(strFavorite); } objRecentNode = treCharacterList.FindNode("Recent", false); if (objRecentNode == null && lstRecents.Count > 0) { objRecentNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_RecentCharacters", GlobalOptions.Language)) { Tag = "Recent" }; blnAddRecentNode = true; } lstRecentsNodes = new TreeNode[lstRecents.Count]; } Parallel.Invoke( () => { if (objFavouriteNode != null && lstFavoritesNodes != null) { object lstFavoritesNodesLock = new object(); Parallel.For(0, lstFavorites.Count, i => { string strFile = lstFavorites[i]; TreeNode objNode = CacheCharacter(strFile); lock (lstFavoritesNodesLock) lstFavoritesNodes[i] = objNode; }); if (blnAddFavouriteNode) { for (int i = 0; i < lstFavoritesNodes.Length; i++) { TreeNode objNode = lstFavoritesNodes[i]; if (objNode != null) { objFavouriteNode.Nodes.Add(objNode); } } } } }, () => { if (objRecentNode != null && lstRecentsNodes != null) { object lstRecentsNodesLock = new object(); Parallel.For(0, lstRecents.Count, i => { string strFile = lstRecents[i]; TreeNode objNode = CacheCharacter(strFile); lock (lstRecentsNodesLock) lstRecentsNodes[i] = objNode; }); if (blnAddRecentNode) { for (int i = 0; i < lstRecentsNodes.Length; i++) { TreeNode objNode = lstRecentsNodes[i]; if (objNode != null) { objRecentNode.Nodes.Add(objNode); } } } } }, () => { if (objWatchNode != null && lstWatchNodes != null) { object lstWatchNodesLock = new object(); Parallel.For(0, lstWatch.Count, i => { string strFile = lstWatch[i]; TreeNode objNode = CacheCharacter(strFile); lock (lstWatchNodesLock) lstWatchNodes[i] = objNode; }); if (blnAddWatchNode) { for (int i = 0; i < lstWatchNodes.Length; i++) { TreeNode objNode = lstWatchNodes[i]; if (objNode != null) { objWatchNode.Nodes.Add(objNode); } } } } }); if (objFavouriteNode != null) { if (blnAddFavouriteNode) { treCharacterList.Nodes.Add(objFavouriteNode); objFavouriteNode.Expand(); } else { objFavouriteNode.Nodes.Clear(); for (int i = 0; i < lstFavoritesNodes.Length; i++) { TreeNode objNode = lstFavoritesNodes[i]; if (objNode != null) { objFavouriteNode.Nodes.Add(objNode); } } } } if (objRecentNode != null) { if (blnAddRecentNode) { treCharacterList.Nodes.Add(objRecentNode); objRecentNode.Expand(); } else { objRecentNode.Nodes.Clear(); for (int i = 0; i < lstRecentsNodes.Length; i++) { TreeNode objNode = lstRecentsNodes[i]; if (objNode != null) { objRecentNode.Nodes.Add(objNode); } } } } if (objWatchNode != null) { if (blnAddWatchNode) { treCharacterList.Nodes.Add(objWatchNode); objWatchNode.Expand(); } else { objWatchNode.Nodes.Clear(); for (int i = 0; i < lstWatchNodes.Length; i++) { TreeNode objNode = lstWatchNodes[i]; if (objNode != null) { objWatchNode.Nodes.Add(objNode); } } } } treCharacterList.ExpandAll(); }
public void LoadCharacters(bool blnRefreshFavorites = true, bool blnRefreshRecents = true, bool blnRefreshWatch = true, bool blnRefreshPlugins = true) { ReadOnlyObservableCollection <string> lstFavorites = new ReadOnlyObservableCollection <string>(GlobalOptions.FavoritedCharacters); bool blnAddFavoriteNode = false; TreeNode objFavoriteNode = null; TreeNode[] lstFavoritesNodes = null; if (blnRefreshFavorites) { objFavoriteNode = treCharacterList.FindNode("Favorite", false); if (objFavoriteNode == null) { objFavoriteNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_FavoriteCharacters")) { Tag = "Favorite" }; blnAddFavoriteNode = true; } lstFavoritesNodes = new TreeNode[lstFavorites.Count]; } List <string> lstRecents = new List <string>(GlobalOptions.MostRecentlyUsedCharacters); Dictionary <string, string> dicWatch = new Dictionary <string, string>(); int intWatchFolderCount = 0; if (!string.IsNullOrEmpty(GlobalOptions.CharacterRosterPath) && Directory.Exists(GlobalOptions.CharacterRosterPath)) { intWatchFolderCount++; foreach (string strFile in Directory.GetFiles(GlobalOptions.CharacterRosterPath, "*.chum5", SearchOption.AllDirectories)) { // Make sure we're not loading a character that was already loaded by the MRU list. if (lstFavorites.Contains(strFile) || lstRecents.Contains(strFile)) { continue; } FileInfo objInfo = new FileInfo(strFile); if (objInfo.Directory == null || objInfo.Directory.FullName == GlobalOptions.CharacterRosterPath) { dicWatch.Add(strFile, "Watch"); continue; } string strNewParent = objInfo.Directory.FullName.Replace(GlobalOptions.CharacterRosterPath + "\\", string.Empty); dicWatch.Add(strFile, strNewParent); } intWatchFolderCount++; } bool blnAddWatchNode = false; TreeNode objWatchNode = null; TreeNode[] lstWatchNodes = null; if (blnRefreshWatch) { objWatchNode = treCharacterList.FindNode("Watch", false); objWatchNode?.Remove(); blnAddWatchNode = dicWatch.Count > 0; if (blnAddWatchNode) { objWatchNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_WatchFolder")) { Tag = "Watch" }; } lstWatchNodes = new TreeNode[intWatchFolderCount]; } bool blnAddRecentNode = false; TreeNode objRecentNode = null; TreeNode[] lstRecentsNodes = null; if (blnRefreshRecents) { // Add any characters that are open to the displayed list so we can have more than 10 characters listed foreach (CharacterShared objCharacterForm in Program.MainForm.OpenCharacterForms) { string strFile = objCharacterForm.CharacterObject.FileName; // Make sure we're not loading a character that was already loaded by the MRU list. if (lstFavorites.Contains(strFile) || lstRecents.Contains(strFile) || dicWatch.ContainsValue(strFile)) { continue; } lstRecents.Add(strFile); } foreach (string strFavorite in lstFavorites) { lstRecents.Remove(strFavorite); } objRecentNode = treCharacterList.FindNode("Recent", false); if (objRecentNode == null && lstRecents.Count > 0) { objRecentNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_RecentCharacters")) { Tag = "Recent" }; blnAddRecentNode = true; } lstRecentsNodes = new TreeNode[lstRecents.Count]; } Parallel.Invoke( () => { if (objFavoriteNode != null && lstFavoritesNodes != null) { object lstFavoritesNodesLock = new object(); Parallel.For(0, lstFavorites.Count, i => { string strFile = lstFavorites[i]; TreeNode objNode = CacheCharacter(strFile); lock (lstFavoritesNodesLock) lstFavoritesNodes[i] = objNode; }); if (blnAddFavoriteNode) { foreach (TreeNode objNode in lstFavoritesNodes) { if (objNode != null) { objFavoriteNode.Nodes.Add(objNode); } } } } }, () => { if (objRecentNode != null && lstRecentsNodes != null) { object lstRecentsNodesLock = new object(); Parallel.For(0, lstRecents.Count, i => { string strFile = lstRecents[i]; TreeNode objNode = CacheCharacter(strFile); lock (lstRecentsNodesLock) lstRecentsNodes[i] = objNode; }); if (blnAddRecentNode) { foreach (TreeNode objNode in lstRecentsNodes) { if (objNode != null) { objRecentNode.Nodes.Add(objNode); } } } } }, () => { if (objWatchNode != null && lstWatchNodes != null) { ConcurrentBag <KeyValuePair <TreeNode, string> > bagNodes = new ConcurrentBag <KeyValuePair <TreeNode, string> >(); Parallel.ForEach(dicWatch, i => bagNodes.Add(new KeyValuePair <TreeNode, string>(CacheCharacter(i.Key), i.Value))); if (blnAddWatchNode) { foreach (string s in dicWatch.Values.Distinct()) { if (s == "Watch") { continue; } objWatchNode.Nodes.Add(new TreeNode(s) { Tag = s }); } foreach (KeyValuePair <TreeNode, string> kvtNode in bagNodes) { if (kvtNode.Value == "Watch") { objWatchNode.Nodes.Add(kvtNode.Key); } else { foreach (TreeNode objNode in objWatchNode.Nodes) { if (objNode.Tag.ToString() == kvtNode.Value) { objNode.Nodes.Add(kvtNode.Key); } } } } } } }, () => { foreach (IPlugin plugin in Program.PluginLoader.MyActivePlugins) { #pragma warning disable CA2008 // Do not create tasks without passing a TaskScheduler var t = Task.Factory.StartNew <ICollection <TreeNode> >(() => { Log.Info("Starting new Task to get CharacterRosterTreeNodes for plugin:" + plugin); var task = plugin.GetCharacterRosterTreeNode(this, blnRefreshPlugins); if (task.Result != null) { return(task.Result.OrderBy(a => a.Text).ToList()); } return(new List <TreeNode>()); }); t.ContinueWith(nodelist => { foreach (TreeNode node in nodelist.Result) { TreeNode objExistingNode = treCharacterList.Nodes.Cast <TreeNode>().FirstOrDefault(x => x.Text == node.Text && x.Tag == node.Tag); Program.MainForm.DoThreadSafe(() => { try { if (objExistingNode != null) { treCharacterList.Nodes.Remove(objExistingNode); } if (node.Nodes.Count > 0 || !string.IsNullOrEmpty(node.ToolTipText) || node.Tag != null) { if (treCharacterList.IsDisposed) { return; } if (treCharacterList.Nodes.ContainsKey(node.Name)) { treCharacterList.Nodes.RemoveByKey(node.Name); } treCharacterList.Nodes.Insert(1, node); } node.Expand(); } catch (ObjectDisposedException e) { Log.Trace(e); } catch (InvalidAsynchronousStateException e) { Log.Trace(e); } catch (ArgumentException e) { Log.Trace(e); } catch (Exception e) { Log.Warn(e); } }); } Log.Info("Task to get and add CharacterRosterTreeNodes for plugin " + plugin + " finished."); }); #pragma warning restore CA2008 // Do not create tasks without passing a TaskScheduler } }); Log.Info("Populating CharacterRosterTreeNode (MainThread)."); if (objFavoriteNode != null) { if (blnAddFavoriteNode) { treCharacterList.Nodes.Add(objFavoriteNode); objFavoriteNode.Expand(); } else { objFavoriteNode.Nodes.Clear(); foreach (TreeNode objNode in lstFavoritesNodes) { if (objNode != null) { objFavoriteNode.Nodes.Add(objNode); } } } } if (objRecentNode != null) { if (blnAddRecentNode) { treCharacterList.Nodes.Add(objRecentNode); objRecentNode.Expand(); } else { try { objRecentNode.Nodes.Clear(); foreach (TreeNode objNode in lstRecentsNodes) { if (objNode != null) { objRecentNode.Nodes.Add(objNode); } } } catch (ObjectDisposedException e) { //just swallow this Log.Trace(e, "ObjectDisposedException can be ignored here."); } } } if (objWatchNode != null) { if (blnAddWatchNode) { treCharacterList.Nodes.Add(objWatchNode); objWatchNode.Expand(); } else { objWatchNode.Nodes.Clear(); foreach (TreeNode objNode in lstWatchNodes) { if (objNode != null) { objWatchNode.Nodes.Add(objNode); } } } } treCharacterList.ExpandAll(); UpdateCharacter(treCharacterList.SelectedNode?.Tag as CharacterCache); }
public void LoadCharacters(bool blnRefreshFavorites = true, bool blnRefreshRecents = true, bool blnRefreshWatch = true, bool blnRefreshPlugins = true) { ReadOnlyObservableCollection<string> lstFavorites = new ReadOnlyObservableCollection<string>(GlobalOptions.FavoritedCharacters); bool blnAddFavouriteNode = false; TreeNode objFavouriteNode = null; TreeNode[] lstFavoritesNodes = null; if(blnRefreshFavorites) { objFavouriteNode = treCharacterList.FindNode("Favourite", false); if(objFavouriteNode == null) { objFavouriteNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_FavouriteCharacters", GlobalOptions.Language)) { Tag = "Favourite" }; blnAddFavouriteNode = true; } lstFavoritesNodes = new TreeNode[lstFavorites.Count]; } IList<string> lstRecents = new List<string>(GlobalOptions.MostRecentlyUsedCharacters); List<string> lstWatch = new List<string>(); if(!string.IsNullOrEmpty(GlobalOptions.CharacterRosterPath) && Directory.Exists(GlobalOptions.CharacterRosterPath)) { string[] objFiles = Directory.GetFiles(GlobalOptions.CharacterRosterPath, "*.chum5"); for(int i = 0; i < objFiles.Length; ++i) { string strFile = objFiles[i]; // Make sure we're not loading a character that was already loaded by the MRU list. if(lstFavorites.Contains(strFile) || lstRecents.Contains(strFile)) continue; lstWatch.Add(strFile); } } bool blnAddWatchNode = false; TreeNode objWatchNode = null; TreeNode[] lstWatchNodes = null; if(blnRefreshWatch) { objWatchNode = treCharacterList.FindNode("Watch", false); if(objWatchNode == null && lstWatch.Count > 0) { objWatchNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_WatchFolder", GlobalOptions.Language)) { Tag = "Watch" }; blnAddWatchNode = true; } lstWatchNodes = new TreeNode[lstWatch.Count]; } bool blnAddRecentNode = false; TreeNode objRecentNode = null; TreeNode[] lstRecentsNodes = null; if(blnRefreshRecents) { // Add any characters that are open to the displayed list so we can have more than 10 characters listed foreach(CharacterShared objCharacterForm in Program.MainForm.OpenCharacterForms) { string strFile = objCharacterForm.CharacterObject.FileName; // Make sure we're not loading a character that was already loaded by the MRU list. if(lstFavorites.Contains(strFile) || lstRecents.Contains(strFile) || lstWatch.Contains(strFile)) continue; lstRecents.Add(strFile); } foreach(string strFavorite in lstFavorites) lstRecents.Remove(strFavorite); objRecentNode = treCharacterList.FindNode("Recent", false); if(objRecentNode == null && lstRecents.Count > 0) { objRecentNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_RecentCharacters", GlobalOptions.Language)) { Tag = "Recent" }; blnAddRecentNode = true; } lstRecentsNodes = new TreeNode[lstRecents.Count]; } Parallel.Invoke( () => { if(objFavouriteNode != null && lstFavoritesNodes != null) { object lstFavoritesNodesLock = new object(); Parallel.For(0, lstFavorites.Count, i => { string strFile = lstFavorites[i]; TreeNode objNode = CacheCharacter(strFile); lock(lstFavoritesNodesLock) lstFavoritesNodes[i] = objNode; }); if(blnAddFavouriteNode) { for(int i = 0; i < lstFavoritesNodes.Length; i++) { TreeNode objNode = lstFavoritesNodes[i]; if(objNode != null) objFavouriteNode.Nodes.Add(objNode); } } } }, () => { if(objRecentNode != null && lstRecentsNodes != null) { object lstRecentsNodesLock = new object(); Parallel.For(0, lstRecents.Count, i => { string strFile = lstRecents[i]; TreeNode objNode = CacheCharacter(strFile); lock(lstRecentsNodesLock) lstRecentsNodes[i] = objNode; }); if(blnAddRecentNode) { for(int i = 0; i < lstRecentsNodes.Length; i++) { TreeNode objNode = lstRecentsNodes[i]; if(objNode != null) objRecentNode.Nodes.Add(objNode); } } } }, () => { if(objWatchNode != null && lstWatchNodes != null) { object lstWatchNodesLock = new object(); Parallel.For(0, lstWatch.Count, i => { string strFile = lstWatch[i]; TreeNode objNode = CacheCharacter(strFile); lock(lstWatchNodesLock) lstWatchNodes[i] = objNode; }); if(blnAddWatchNode) { for(int i = 0; i < lstWatchNodes.Length; i++) { TreeNode objNode = lstWatchNodes[i]; if(objNode != null) objWatchNode.Nodes.Add(objNode); } } } }, () => { foreach(var plugin in Program.MainForm.PluginLoader.MyActivePlugins) { var t = Task.Factory.StartNew<IEnumerable<List<TreeNode>>>(() => { System.Diagnostics.Trace.TraceInformation("Starting new Task to get CharacterRosterTreeNodes for plugin:" + plugin.ToString()); var result = new List<List<TreeNode>>(); var task = plugin.GetCharacterRosterTreeNode(this, blnRefreshPlugins); if(task.Result != null) { result.Add(task.Result.ToList()); } return result; }); t.ContinueWith((nodestask) => { foreach(var nodelist in nodestask.Result) { foreach(var node in nodelist) { var querycoll = treCharacterList.Nodes.Cast<TreeNode>(); var found = from a in querycoll where a.Text == node.Text && a.Tag == node.Tag select a; Program.MainForm.DoThreadSafe(() => { if(found.Any()) { treCharacterList.Nodes.Remove(found.FirstOrDefault()); } if ((node.Nodes.Count > 0 || !String.IsNullOrEmpty(node.ToolTipText)) || (node.Tag != null)) treCharacterList.Nodes.Insert(1, node); node.Expand(); }); } } System.Diagnostics.Trace.TraceInformation("Task to get and add CharacterRosterTreeNodes for plugin " + plugin.ToString() + " finished."); }); } }); System.Diagnostics.Trace.TraceInformation("Populating CharacterRosterTreeNode (MainThread)."); if(objFavouriteNode != null) { if(blnAddFavouriteNode) { treCharacterList.Nodes.Add(objFavouriteNode); objFavouriteNode.Expand(); } else { objFavouriteNode.Nodes.Clear(); for(int i = 0; i < lstFavoritesNodes.Length; i++) { TreeNode objNode = lstFavoritesNodes[i]; if(objNode != null) objFavouriteNode.Nodes.Add(objNode); } } } if(objRecentNode != null) { if(blnAddRecentNode) { treCharacterList.Nodes.Add(objRecentNode); objRecentNode.Expand(); } else { objRecentNode.Nodes.Clear(); for(int i = 0; i < lstRecentsNodes.Length; i++) { TreeNode objNode = lstRecentsNodes[i]; if(objNode != null) objRecentNode.Nodes.Add(objNode); } } } if(objWatchNode != null) { if(blnAddWatchNode) { treCharacterList.Nodes.Add(objWatchNode); objWatchNode.Expand(); } else { objWatchNode.Nodes.Clear(); for(int i = 0; i < lstWatchNodes.Length; i++) { TreeNode objNode = lstWatchNodes[i]; if(objNode != null) objWatchNode.Nodes.Add(objNode); } } } treCharacterList.ExpandAll(); }
public bool Contains(TOut item) { return(_ReadOnlyCollection.Contains(item)); }
public async Task LoadCharacters(bool blnRefreshFavorites = true, bool blnRefreshRecents = true, bool blnRefreshWatch = true, bool blnRefreshPlugins = true) { _blnSkipUpdate = true; ReadOnlyObservableCollection <string> lstFavorites = new ReadOnlyObservableCollection <string>(GlobalOptions.FavoritedCharacters); bool blnAddFavoriteNode = false; TreeNode objFavoriteNode = null; TreeNode[] lstFavoritesNodes = null; if (blnRefreshFavorites) { objFavoriteNode = treCharacterList.FindNode("Favorite", false); if (objFavoriteNode == null) { objFavoriteNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_FavoriteCharacters")) { Tag = "Favorite" }; blnAddFavoriteNode = true; } lstFavoritesNodes = new TreeNode[lstFavorites.Count]; } List <string> lstRecents = new List <string>(GlobalOptions.MostRecentlyUsedCharacters); Dictionary <string, string> dicWatch = new Dictionary <string, string>(); if (!string.IsNullOrEmpty(GlobalOptions.CharacterRosterPath) && Directory.Exists(GlobalOptions.CharacterRosterPath)) { foreach (string strFile in Directory.GetFiles(GlobalOptions.CharacterRosterPath, "*.chum5", SearchOption.AllDirectories)) { // Make sure we're not loading a character that was already loaded by the MRU list. if (lstFavorites.Contains(strFile) || lstRecents.Contains(strFile)) { continue; } FileInfo objInfo = new FileInfo(strFile); if (objInfo.Directory == null || objInfo.Directory.FullName == GlobalOptions.CharacterRosterPath) { dicWatch.Add(strFile, "Watch"); continue; } string strNewParent = objInfo.Directory.FullName.Replace(GlobalOptions.CharacterRosterPath + "\\", string.Empty); dicWatch.Add(strFile, strNewParent); } } bool blnAddWatchNode = false; TreeNode objWatchNode = null; if (blnRefreshWatch) { objWatchNode = treCharacterList.FindNode("Watch", false); blnAddWatchNode = dicWatch.Count > 0; if (blnAddWatchNode) { if (objWatchNode != null) { objWatchNode.Nodes.Clear(); } else { objWatchNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_WatchFolder")) { Tag = "Watch" } }; } else { objWatchNode?.Remove(); } } bool blnAddRecentNode = false; TreeNode objRecentNode = null; TreeNode[] lstRecentsNodes = null; if (blnRefreshRecents) { // Add any characters that are open to the displayed list so we can have more than 10 characters listed foreach (CharacterShared objCharacterForm in Program.MainForm.OpenCharacterForms) { string strFile = objCharacterForm.CharacterObject.FileName; // Make sure we're not loading a character that was already loaded by the MRU list. if (lstFavorites.Contains(strFile) || lstRecents.Contains(strFile) || dicWatch.ContainsValue(strFile)) { continue; } lstRecents.Add(strFile); } foreach (string strFavorite in lstFavorites) { lstRecents.Remove(strFavorite); } objRecentNode = treCharacterList.FindNode("Recent", false); if (objRecentNode == null && lstRecents.Count > 0) { objRecentNode = new TreeNode(LanguageManager.GetString("Treenode_Roster_RecentCharacters")) { Tag = "Recent" }; blnAddRecentNode = true; } lstRecentsNodes = new TreeNode[lstRecents.Count]; } await Task.WhenAll( Task.Run(() => { if (lstFavoritesNodes == null || lstFavorites.Count <= 0) { return; } Parallel.For(0, lstFavorites.Count, i => lstFavoritesNodes[i] = CacheCharacter(lstFavorites[i])); if (!blnAddFavoriteNode || objFavoriteNode == null) { return; } foreach (TreeNode objNode in lstFavoritesNodes) { if (objNode == null) { continue; } if (objFavoriteNode.TreeView != null) { objFavoriteNode.TreeView.DoThreadSafe(() => objFavoriteNode.Nodes.Add(objNode)); } else { objFavoriteNode.Nodes.Add(objNode); } } }), Task.Run(() => { if (lstRecentsNodes == null || lstRecents.Count <= 0) { return; } Parallel.For(0, lstRecents.Count, i => lstRecentsNodes[i] = CacheCharacter(lstRecents[i])); if (!blnAddRecentNode || objRecentNode == null) { return; } foreach (TreeNode objNode in lstRecentsNodes) { if (objNode == null) { continue; } if (objRecentNode.TreeView != null) { objRecentNode.TreeView.DoThreadSafe(() => objRecentNode.Nodes.Add(objNode)); } else { objRecentNode.Nodes.Add(objNode); } } }), Task.Run(() => { if (objWatchNode == null || !blnAddWatchNode || dicWatch.Count <= 0) { return; } ConcurrentDictionary <TreeNode, string> dicWatchNodes = new ConcurrentDictionary <TreeNode, string>(); Parallel.ForEach(dicWatch, kvpLoop => dicWatchNodes.TryAdd(CacheCharacter(kvpLoop.Key), kvpLoop.Value)); foreach (string s in dicWatchNodes.Values.Distinct()) { if (s == "Watch") { continue; } if (objWatchNode.TreeView != null) { objWatchNode.TreeView.DoThreadSafe(() => objWatchNode.Nodes.Add(new TreeNode(s) { Tag = s })); } else { objWatchNode.Nodes.Add(new TreeNode(s) { Tag = s }); } } foreach (KeyValuePair <TreeNode, string> kvtNode in dicWatchNodes) { if (kvtNode.Value == "Watch") { if (objWatchNode.TreeView != null) { objWatchNode.TreeView.DoThreadSafe(() => objWatchNode.Nodes.Add(kvtNode.Key)); } else { objWatchNode.Nodes.Add(kvtNode.Key); } } else { foreach (TreeNode objNode in objWatchNode.Nodes) { if (objNode.Tag.ToString() == kvtNode.Value) { if (objWatchNode.TreeView != null) { objWatchNode.TreeView.DoThreadSafe(() => objWatchNode.Nodes.Add(kvtNode.Key)); } else { objNode.Nodes.Add(kvtNode.Key); } } } } } }), Task.Run(async() => { foreach (IPlugin plugin in Program.PluginLoader.MyActivePlugins) { Log.Info("Starting new Task to get CharacterRosterTreeNodes for plugin:" + plugin); List <TreeNode> lstNodes = (await plugin.GetCharacterRosterTreeNode(this, blnRefreshPlugins))?.OrderBy(a => a.Text).ToList() ?? new List <TreeNode>(); foreach (TreeNode node in lstNodes) { TreeNode objExistingNode = treCharacterList.Nodes.Cast <TreeNode>() .FirstOrDefault(x => x.Text == node.Text && x.Tag == node.Tag); try { if (objExistingNode != null) { await treCharacterList.DoThreadSafeAsync(() => treCharacterList.Nodes.Remove(objExistingNode)); } if (node.Nodes.Count > 0 || !string.IsNullOrEmpty(node.ToolTipText) || node.Tag != null) { if (treCharacterList.IsNullOrDisposed()) { return; } await treCharacterList.DoThreadSafeAsync(() => { if (treCharacterList.Nodes.ContainsKey(node.Name)) { treCharacterList.Nodes.RemoveByKey(node.Name); } treCharacterList.Nodes.Insert(1, node); }); } await treCharacterList.DoThreadSafeAsync(() => node.Expand()); } catch (ObjectDisposedException e) { Log.Trace(e); } catch (InvalidAsynchronousStateException e) { Log.Trace(e); } catch (ArgumentException e) { Log.Trace(e); } catch (Exception e) { Log.Warn(e); } } Log.Info("Task to get and add CharacterRosterTreeNodes for plugin " + plugin + " finished."); } })); Log.Info("Populating CharacterRosterTreeNode (MainThread)."); await treCharacterList.DoThreadSafeAsync(() => { treCharacterList.SuspendLayout(); if (objFavoriteNode != null) { if (blnAddFavoriteNode) { treCharacterList.Nodes.Add(objFavoriteNode); objFavoriteNode.Expand(); } else if (lstFavoritesNodes != null) { objFavoriteNode.Nodes.Clear(); foreach (TreeNode objNode in lstFavoritesNodes) { if (objNode != null) { objFavoriteNode.Nodes.Add(objNode); } } } } if (objRecentNode != null) { if (blnAddRecentNode) { treCharacterList.Nodes.Add(objRecentNode); objRecentNode.Expand(); } else if (lstRecentsNodes != null) { try { objRecentNode.Nodes.Clear(); foreach (TreeNode objNode in lstRecentsNodes) { if (objNode != null) { objRecentNode.Nodes.Add(objNode); } } } catch (ObjectDisposedException e) { //just swallow this Log.Trace(e, "ObjectDisposedException can be ignored here."); } } } if (objWatchNode != null && blnAddWatchNode) { if (objWatchNode.TreeView == null) { treCharacterList.Nodes.Add(objWatchNode); } objWatchNode.Expand(); } treCharacterList.ExpandAll(); treCharacterList.ResumeLayout(); }); await this.DoThreadSafeAsync(() => UpdateCharacter(treCharacterList.SelectedNode?.Tag as CharacterCache)); _blnSkipUpdate = false; }