Browse Source

Parallel stacks - Tasks view v0.1

pull/15/head
Eusebiu Marcu 15 years ago
parent
commit
1326cb47e7
  1. 159
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs
  2. 13
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs

159
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs

@ -52,11 +52,11 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
protected override void SelectProcess(Process process) protected override void SelectProcess(Process process)
{ {
if (debuggedProcess != null) { if (debuggedProcess != null) {
debuggedProcess.Paused -= debuggedProcess_Paused; debuggedProcess.Paused -= OnProcessPaused;
} }
debuggedProcess = process; debuggedProcess = process;
if (debuggedProcess != null) { if (debuggedProcess != null) {
debuggedProcess.Paused += debuggedProcess_Paused; debuggedProcess.Paused += OnProcessPaused;
} }
DebuggerService.DebugStarted += OnReset; DebuggerService.DebugStarted += OnReset;
@ -71,9 +71,11 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
return; return;
} }
LoggingService.InfoFormatted("Start refresh: {0}" + Environment.NewLine, parallelStacksView);
currentThreadStacks.Clear(); currentThreadStacks.Clear();
using(new PrintTimes("Parallel stack - method view + threads refresh")) { using(new PrintTimes("Parallel stack - create stacks refresh")) {
try { try {
// create all simple ThreadStacks // create all simple ThreadStacks
foreach (Thread thread in debuggedProcess.Threads) { foreach (Thread thread in debuggedProcess.Threads) {
@ -163,7 +165,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
BookmarkManager.RemoveAll(b => b is SelectedFrameBookmark); BookmarkManager.RemoveAll(b => b is SelectedFrameBookmark);
} }
private void debuggedProcess_Paused(object sender, ProcessEventArgs e) private void OnProcessPaused(object sender, ProcessEventArgs e)
{ {
RefreshPad(); RefreshPad();
} }
@ -305,7 +307,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
// create new parent stack // create new parent stack
ThreadStack commonParent = new ThreadStack(); ThreadStack commonParent = new ThreadStack();
commonParent.UpdateThreadIds(threadIds.ToArray()); commonParent.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, threadIds.ToArray());
commonParent.ItemCollection = parentItems.ToObservable(); commonParent.ItemCollection = parentItems.ToObservable();
commonParent.Process = debuggedProcess; commonParent.Process = debuggedProcess;
commonParent.StackSelected += OnThreadStackSelected; commonParent.StackSelected += OnThreadStackSelected;
@ -333,7 +335,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
// update thread ids // update thread ids
if (commonParent.ThreadStackParents != null) { if (commonParent.ThreadStackParents != null) {
commonParent.ThreadStackParents[0].UpdateThreadIds(commonParent.ThreadIds.ToArray()); commonParent.ThreadStackParents[0].UpdateThreadIds(
parallelStacksView == ParallelStacksView.Tasks,
commonParent.ThreadIds.ToArray());
} }
stack.ThreadStackParents.Clear(); stack.ThreadStackParents.Clear();
@ -361,7 +365,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
break; break;
} }
if (isOver) if (isOver || currentThreadStacks.Count == 0)
break; break;
} }
} }
@ -384,18 +388,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
ThreadStack common = new ThreadStack(); ThreadStack common = new ThreadStack();
var observ = new ObservableCollection<ExpandoObject>(); var observ = new ObservableCollection<ExpandoObject>();
bool dummy = false; bool dummy = false;
dynamic obj; dynamic obj = CreateItemForFrame(selectedFrame, ref dummy);
if (parallelStacksView == ParallelStacksView.Threads)
obj = CreateItemForThread(selectedFrame, selectedFrame.Thread, ref dummy);
else
obj = CreateItemForTask(selectedFrame, selectedFrame.Thread, ref dummy);
obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source; obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source;
observ.Add(obj); observ.Add(obj);
common.ItemCollection = observ; common.ItemCollection = observ;
common.StackSelected += OnThreadStackSelected; common.StackSelected += OnThreadStackSelected;
common.FrameSelected += OnFrameSelected; common.FrameSelected += OnFrameSelected;
common.UpdateThreadIds(selectedFrame.Thread.ID); common.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, selectedFrame.Thread.ID);
common.Process = debuggedProcess; common.Process = debuggedProcess;
common.ThreadStackChildren = new List<ThreadStack>(); common.ThreadStackChildren = new List<ThreadStack>();
common.ThreadStackParents = new List<ThreadStack>(); common.ThreadStackParents = new List<ThreadStack>();
@ -410,7 +409,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
topStack.ItemCollection = tuple.Item1; topStack.ItemCollection = tuple.Item1;
topStack.StackSelected += OnThreadStackSelected; topStack.StackSelected += OnThreadStackSelected;
topStack.FrameSelected += OnFrameSelected; topStack.FrameSelected += OnFrameSelected;
topStack.UpdateThreadIds(tuple.Item3.ToArray()); topStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
topStack.Process = debuggedProcess; topStack.Process = debuggedProcess;
topStack.ThreadStackParents = new List<ThreadStack>(); topStack.ThreadStackParents = new List<ThreadStack>();
topStack.ThreadStackParents.Add(common); topStack.ThreadStackParents.Add(common);
@ -426,11 +425,11 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
bottomStack.ItemCollection = tuple.Item2; bottomStack.ItemCollection = tuple.Item2;
bottomStack.StackSelected += OnThreadStackSelected; bottomStack.StackSelected += OnThreadStackSelected;
bottomStack.FrameSelected += OnFrameSelected; bottomStack.FrameSelected += OnFrameSelected;
bottomStack.UpdateThreadIds(tuple.Item3.ToArray()); bottomStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
bottomStack.Process = debuggedProcess; bottomStack.Process = debuggedProcess;
bottomStack.ThreadStackChildren = new List<ThreadStack>(); bottomStack.ThreadStackChildren = new List<ThreadStack>();
bottomStack.ThreadStackChildren.Add(common); bottomStack.ThreadStackChildren.Add(common);
common.UpdateThreadIds(tuple.Item3.ToArray()); common.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
common.ThreadStackParents.Add(bottomStack); common.ThreadStackParents.Add(bottomStack);
currentThreadStacks.Add(bottomStack); currentThreadStacks.Add(bottomStack);
} }
@ -449,9 +448,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
ThreadStack threadStack = new ThreadStack(); ThreadStack threadStack = new ThreadStack();
threadStack.StackSelected += OnThreadStackSelected; threadStack.StackSelected += OnThreadStackSelected;
threadStack.FrameSelected += OnFrameSelected; threadStack.FrameSelected += OnFrameSelected;
threadStack.UpdateThreadIds(thread.ID);
threadStack.Process = debuggedProcess; threadStack.Process = debuggedProcess;
threadStack.ItemCollection = items; threadStack.ItemCollection = items;
threadStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, thread.ID);
if (debuggedProcess.SelectedThread != null) { if (debuggedProcess.SelectedThread != null) {
threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID); threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
@ -465,24 +464,63 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
private ObservableCollection<ExpandoObject> CreateItems(Thread thread) private ObservableCollection<ExpandoObject> CreateItems(Thread thread)
{ {
bool lastItemIsExternalMethod = false; bool lastItemIsExternalMethod = false;
int noTasks = 0;
var result = new ObservableCollection<ExpandoObject>(); var result = new ObservableCollection<ExpandoObject>();
foreach (StackFrame frame in thread.GetCallstack(100)) { var callstack = thread.GetCallstack(100);
dynamic obj;
if (parallelStacksView == ParallelStacksView.Threads) if (parallelStacksView == ParallelStacksView.Threads) {
obj = CreateItemForThread(frame, thread, ref lastItemIsExternalMethod); foreach (StackFrame frame in callstack) {
else dynamic obj = CreateItemForFrame(frame, ref lastItemIsExternalMethod);
obj = CreateItemForTask(frame, thread, ref lastItemIsExternalMethod);
if (obj != null)
result.Add(obj);
}
} else {
for (int i = 0 ; i < callstack.Length; ++i) {
StackFrame frame = callstack[i];
dynamic 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);
}
if (obj != null) Utils.DoEvents(debuggedProcess);
result.Add(obj); // return null if we are dealing with a simple thread
return noTasks == 0 ? null : result;
} }
Utils.DoEvents(debuggedProcess); Utils.DoEvents(debuggedProcess);
return result; return result;
} }
private ExpandoObject CreateItemForThread(StackFrame frame, Thread thread, ref bool lastItemIsExternalMethod) private ExpandoObject CreateItemForFrame(StackFrame frame, ref bool lastItemIsExternalMethod)
{ {
dynamic obj = new ExpandoObject(); dynamic obj = new ExpandoObject();
string fullName; string fullName;
@ -501,54 +539,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
lastItemIsExternalMethod = true; lastItemIsExternalMethod = true;
} }
if (thread.SelectedStackFrame != null && if (frame.Thread.SelectedStackFrame != null &&
thread.ID == debuggedProcess.SelectedThread.ID && frame.Thread.ID == debuggedProcess.SelectedThread.ID &&
thread.SelectedStackFrame.IP == frame.IP && frame.Thread.SelectedStackFrame.IP == frame.IP &&
thread.SelectedStackFrame.GetMethodName() == frame.GetMethodName()) { frame.Thread.SelectedStackFrame.GetMethodName() == frame.GetMethodName()) {
obj.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source; obj.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source;
obj.IsRunningStackFrame = true; obj.IsRunningStackFrame = true;
}
else {
if (selectedFrame != null && frame.Thread.ID == selectedFrame.Thread.ID &&
frame.GetMethodName() == selectedFrame.GetMethodName())
obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source;
else
obj.Image = null;
obj.IsRunningStackFrame = false;
}
obj.MethodName = fullName;
return obj;
}
private ExpandoObject CreateItemForTask(StackFrame frame, Thread thread, ref bool lastItemIsExternalMethod)
{
dynamic obj = new ExpandoObject();
string fullName;
if (frame.HasSymbols) {
// Show the method in the list
fullName = frame.GetMethodName();
lastItemIsExternalMethod = false;
obj.FontWeight = FontWeights.Normal;
obj.Foreground = Brushes.Black;
} else { } else {
// Show [External methods] in the list
if (lastItemIsExternalMethod) return null;
fullName = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ExternalMethods").Trim();
obj.FontWeight = FontWeights.Normal;
obj.Foreground = Brushes.Gray;
lastItemIsExternalMethod = true;
}
if (thread.SelectedStackFrame != null &&
thread.ID == debuggedProcess.SelectedThread.ID &&
thread.SelectedStackFrame.IP == frame.IP &&
thread.SelectedStackFrame.GetMethodName() == frame.GetMethodName()) {
obj.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source;
obj.IsRunningStackFrame = true;
}
else {
if (selectedFrame != null && frame.Thread.ID == selectedFrame.Thread.ID && if (selectedFrame != null && frame.Thread.ID == selectedFrame.Thread.ID &&
frame.GetMethodName() == selectedFrame.GetMethodName()) frame.GetMethodName() == selectedFrame.GetMethodName())
obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source; obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source;
@ -576,7 +573,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
private void OnThreadStackSelected(object sender, EventArgs e) private void OnThreadStackSelected(object sender, EventArgs e)
{ {
foreach (var ts in this.currentThreadStacks.FindAll(ts => ts.ThreadStackChildren == null)) { foreach (var ts in this.currentThreadStacks) {
if (ts.IsSelected) if (ts.IsSelected)
ts.IsSelected = false; ts.IsSelected = false;
ts.ClearImages(); ts.ClearImages();
@ -619,13 +616,25 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
if (listToClone == null) if (listToClone == null)
return null; return null;
List<T> result = new List<T>(); var result = new List<T>();
foreach (var item in listToClone) foreach (var item in listToClone)
result.Add(item); result.Add(item);
return result; return result;
} }
internal static ObservableCollection<T> Clone<T>(this ObservableCollection<T> collectionToClone)
{
if (collectionToClone == null)
return null;
var result = new ObservableCollection<T>();
foreach (var item in collectionToClone)
result.Add(item);
return result;
}
internal static ObservableCollection<T> ToObservable<T>(this Stack<T> stack) internal static ObservableCollection<T> ToObservable<T>(this Stack<T> stack)
{ {
if (stack == null) if (stack == null)

13
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs

@ -111,7 +111,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
#region Public Methods #region Public Methods
public void UpdateThreadIds(params uint[] threadIds) public void UpdateThreadIds(bool isTask, params uint[] threadIds)
{ {
var list = new List<uint>(); var list = new List<uint>();
foreach (uint id in threadIds) { foreach (uint id in threadIds) {
@ -121,10 +121,13 @@ namespace Debugger.AddIn.Pads.ParallelPad
} }
this.threadIds.AddRange(list); this.threadIds.AddRange(list);
if (this.threadIds.Count > 1) if (this.threadIds.Count > 1) {
this.HeaderText.Text = this.threadIds.Count.ToString() + " Threads"; string suffix = isTask ? " Tasks" : " Threads";
else this.HeaderText.Text = this.threadIds.Count.ToString() + suffix;
this.HeaderText.Text = "1 Thread"; }
else {
this.HeaderText.Text = isTask ? "1 Task" : "1 Thread";
}
} }
public void ClearImages() public void ClearImages()

Loading…
Cancel
Save