void CreateThreadStack(Thread thread) { var items = CreateItems(thread); if (items == null || items.Count == 0) { return; } ThreadStack threadStack = new ThreadStack(); threadStack.StackSelected += OnThreadStackSelected; threadStack.FrameSelected += OnFrameSelected; threadStack.Process = debuggedProcess; threadStack.ItemCollection = items; threadStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, thread.ID); if (debuggedProcess.SelectedThread != null) { threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID); if (selectedFrame == null) { selectedFrame = debuggedProcess.SelectedStackFrame; } } currentThreadStacks.Add(threadStack); }
ObservableCollection <ParallelStackFrameModel> CreateItems(Thread thread) { bool lastItemIsExternalMethod = false; int noTasks = 0; var result = new ObservableCollection <ParallelStackFrameModel>(); var callstack = thread.GetCallstack(100); if (parallelStacksView == ParallelStacksView.Threads) { foreach (StackFrame frame in callstack) { ParallelStackFrameModel obj = CreateItemForFrame(frame, ref lastItemIsExternalMethod); if (obj != null) { result.Add(obj); } } } else { for (int i = 0; i < callstack.Length; ++i) { StackFrame frame = callstack[i]; ParallelStackFrameModel obj = CreateItemForFrame(frame, ref lastItemIsExternalMethod); if (frame.MethodInfo.FullName.IndexOf("System.Threading.Tasks.Task.ExecuteEntry") != -1) { noTasks++; } if (noTasks == 1) { if (frame.HasSymbols) { // create thread stack for the items collected until now ThreadStack threadStack = new ThreadStack(); threadStack.StackSelected += OnThreadStackSelected; threadStack.FrameSelected += OnFrameSelected; threadStack.Process = debuggedProcess; threadStack.ItemCollection = result.Clone(); threadStack.UpdateThreadIds(true, frame.Thread.ID); if (debuggedProcess.SelectedThread != null) { threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID); if (selectedFrame == null) { selectedFrame = debuggedProcess.SelectedStackFrame; } } currentThreadStacks.Add(threadStack); // reset result.Clear(); noTasks = 0; } } if (obj != null) { result.Add(obj); } } // return null if we are dealing with a simple thread return(noTasks == 0 ? null : result); } return(result); }
void CreateMethodViewStacks() { var list = new List <Tuple <ObservableCollection <ParallelStackFrameModel>, ObservableCollection <ParallelStackFrameModel>, List <uint> > >(); // find all threadstacks that contains the selected frame for (int i = currentThreadStacks.Count - 1; i >= 0; --i) { var tuple = currentThreadStacks[i].ItemCollection.SplitStack(selectedFrame, currentThreadStacks[i].ThreadIds); if (tuple != null) { list.Add(tuple); } } currentThreadStacks.Clear(); // common ThreadStack common = new ThreadStack(); var observ = new ObservableCollection <ParallelStackFrameModel>(); bool dummy = false; ParallelStackFrameModel obj = CreateItemForFrame(selectedFrame, ref dummy); obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source; observ.Add(obj); common.ItemCollection = observ; common.StackSelected += OnThreadStackSelected; common.FrameSelected += OnFrameSelected; common.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, selectedFrame.Thread.ID); common.Process = debuggedProcess; common.ThreadStackChildren = new List <ThreadStack>(); common.ThreadStackParents = new List <ThreadStack>(); // for all thread stacks, split them in 2 : // one that invokes the method frame, second that get's invoked by current method frame foreach (var tuple in list) { // add top if (tuple.Item1.Count > 0) { ThreadStack topStack = new ThreadStack(); topStack.ItemCollection = tuple.Item1; topStack.StackSelected += OnThreadStackSelected; topStack.FrameSelected += OnFrameSelected; topStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray()); topStack.Process = debuggedProcess; topStack.ThreadStackParents = new List <ThreadStack>(); topStack.ThreadStackParents.Add(common); currentThreadStacks.Add(topStack); common.ThreadStackChildren.Add(topStack); } // add bottom if (tuple.Item2.Count > 0) { ThreadStack bottomStack = new ThreadStack(); bottomStack.ItemCollection = tuple.Item2; bottomStack.StackSelected += OnThreadStackSelected; bottomStack.FrameSelected += OnFrameSelected; bottomStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray()); bottomStack.Process = debuggedProcess; bottomStack.ThreadStackChildren = new List <ThreadStack>(); bottomStack.ThreadStackChildren.Add(common); common.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray()); common.ThreadStackParents.Add(bottomStack); currentThreadStacks.Add(bottomStack); } } currentThreadStacks.Add(common); common.IsSelected = true; }
void CreateCommonStacks() { // stack.ItemCollection order // 0 -> top of stack = S.C // 1 -> ............ = S.B // ....................... // n -> bottom of stack = [External Methods] // ThreadStacks with common frame var commonFrameThreads = new Dictionary <string, List <ThreadStack> >(); bool isOver = false; while (true) { for (int i = currentThreadStacks.Count - 1; i >= 0; --i) { var stack = currentThreadStacks[i]; if (stack.ItemCollection.Count == 0) { currentThreadStacks.Remove(stack); continue; } } //get all thread stacks with common start frame foreach (var stack in currentThreadStacks) { int count = stack.ItemCollection.Count; ParallelStackFrameModel frame = stack.ItemCollection[count - 1]; string fullname = frame.MethodName + stack.Level.ToString(); if (!commonFrameThreads.ContainsKey(fullname)) { commonFrameThreads.Add(fullname, new List <ThreadStack>()); } if (!commonFrameThreads[fullname].Contains(stack)) { commonFrameThreads[fullname].Add(stack); } } // for every list of common stacks, find split place and add them to currentThreadStacks foreach (var frameName in commonFrameThreads.Keys) { var listOfCurrentStacks = commonFrameThreads[frameName]; if (listOfCurrentStacks.Count == 1) // just skip the parents { isOver = true; // we finish when all are pseodo-parents: no more spliting continue; } isOver = false; // find the frameIndex where we can split int frameIndex = 0; string fn = string.Empty; bool canContinue = true; while (canContinue) { for (int i = 0; i < listOfCurrentStacks.Count; ++i) { var stack = listOfCurrentStacks[i]; if (stack.ItemCollection.Count == frameIndex) { canContinue = false; break; } ParallelStackFrameModel item = stack.ItemCollection[stack.ItemCollection.Count - frameIndex - 1]; string currentName = item.MethodName; if (i == 0) { fn = currentName; continue; } if (fn == currentName) { continue; } else { canContinue = false; break; } } if (canContinue) { frameIndex++; } } // remove last [frameIndex] and create a new ThreadStack as the parent of what remained in the children var threadIds = new List <uint>(); var parentItems = new Stack <ParallelStackFrameModel>(); while (frameIndex > 0) { for (int i = 0; i < listOfCurrentStacks.Count; ++i) { var stack = listOfCurrentStacks[i]; int indexToRemove = stack.ItemCollection.Count - 1; #if DEBUG ParallelStackFrameModel d_item = stack.ItemCollection[indexToRemove]; string name = d_item.MethodName; #endif if (i == 0) { parentItems.Push(stack.ItemCollection[indexToRemove]); } stack.ItemCollection.RemoveAt(indexToRemove); } frameIndex--; } // update thread ids for (int i = 0; i < listOfCurrentStacks.Count; ++i) { threadIds.AddRange(listOfCurrentStacks[i].ThreadIds); } // remove stacks with no items for (int i = listOfCurrentStacks.Count - 1; i >= 0; --i) { var stack = listOfCurrentStacks[i]; if (stack.ItemCollection.Count == 0) { listOfCurrentStacks.Remove(stack); } } // increase the Level for (int i = 0; i < listOfCurrentStacks.Count; ++i) { listOfCurrentStacks[i].Level++; } // create new parent stack ThreadStack commonParent = new ThreadStack(); commonParent.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, threadIds.ToArray()); commonParent.ItemCollection = parentItems.ToObservable(); commonParent.Process = debuggedProcess; commonParent.StackSelected += OnThreadStackSelected; commonParent.FrameSelected += OnFrameSelected; commonParent.IsSelected = commonParent.ThreadIds.Contains(debuggedProcess.SelectedThread.ID); // add new children foreach (var stack in listOfCurrentStacks) { if (stack.ItemCollection.Count == 0) { currentThreadStacks.Remove(stack); continue; } ParallelStackFrameModel item = stack.ItemCollection[stack.ItemCollection.Count - 1]; // add the parent to the parent if (stack.ThreadStackParents != null) { // remove stack from it's parent because it will have the commonParent as parent stack.ThreadStackParents[0].ThreadStackChildren.Remove(stack); commonParent.ThreadStackParents = stack.ThreadStackParents.Clone(); commonParent.ThreadStackParents[0].ThreadStackChildren.Add(commonParent); // set level commonParent.Level = stack.Level - 1; } else { stack.ThreadStackParents = new List <ThreadStack>(); } // update thread ids if (commonParent.ThreadStackParents != null) { commonParent.ThreadStackParents[0].UpdateThreadIds( parallelStacksView == ParallelStacksView.Tasks, commonParent.ThreadIds.ToArray()); } stack.ThreadStackParents.Clear(); stack.ThreadStackParents.Add(commonParent); string currentName = item.MethodName + stack.Level.ToString();; // add name or add to list if (!commonFrameThreads.ContainsKey(currentName)) { var newList = new List <ThreadStack>(); newList.Add(stack); commonFrameThreads.Add(currentName, newList); } else { var list = commonFrameThreads[currentName]; list.Add(stack); } } commonParent.ThreadStackChildren = listOfCurrentStacks.Clone(); commonFrameThreads[frameName].Clear(); commonFrameThreads[frameName].Add(commonParent); currentThreadStacks.Add(commonParent); // exit and retry break; } if (isOver || currentThreadStacks.Count == 0) { break; } } }