void UpdateFrames_DbgThread() { dbgManager.Dispatcher.VerifyAccess(); bool raiseActiveFrameIndexChanged, raiseFramesChanged; DbgStackWalker stackWalker = null; DbgStackFrame[] newFrames = null; try { var thread = dbgManager.CurrentThread.Current; if (thread == null || thread.Process.State != DbgProcessState.Paused) { newFrames = Array.Empty <DbgStackFrame>(); } else { stackWalker = thread.CreateStackWalker(); newFrames = stackWalker.GetNextStackFrames(MaxShownFrames + 1); } lock (lockObj) { if (frames.Length > 0) { dbgManager.Close(frames); } int newActiveFrameIndex = GetFrameIndex(newFrames); // Always raise frames-changed event even if old and new arrays have 0 length. raiseFramesChanged = true; raiseActiveFrameIndexChanged = newActiveFrameIndex != activeFrameIndex; // Note that we keep the extra frame so we don't have to create a new array with one less // frame. If we got MaxShownFrames+1 frames, it's not very likely that the last one in the // array is actually the last frame. // Another solution is to create a custom IList<DbgStackFrame> that hides the last one // but that's not worth it. frames = newFrames; readOnlyFrames = newFrames.Length == 0 ? emptyFrames : new ReadOnlyCollection <DbgStackFrame>(newFrames); activeFrameIndex = newActiveFrameIndex; framesTruncated = newFrames.Length > MaxShownFrames; } } finally { stackWalker?.Close(); if (newFrames != null && frames != newFrames && newFrames.Length > 0) { dbgManager.Close(newFrames); } } if (raiseFramesChanged || raiseActiveFrameIndexChanged) { FramesChanged?.Invoke(this, new FramesChangedEventArgs(raiseFramesChanged, raiseActiveFrameIndexChanged)); } }
/// <summary> /// Gets the top stack frame or null if there's none /// </summary> /// <returns></returns> public DbgStackFrame?GetTopStackFrame() { DbgStackWalker?stackWalker = null; try { stackWalker = CreateStackWalker(); var frames = stackWalker.GetNextStackFrames(1); Debug.Assert(frames.Length <= 1); return(frames.Length == 0 ? null : frames[0]); } finally { stackWalker?.Close(); } }
/// <summary> /// Gets the first <paramref name="count"/> frames. /// The returned frame count can be less than <paramref name="count"/> if there's not enough frames available. /// </summary> /// <param name="count">Max number of frames to return</param> /// <returns></returns> public DbgStackFrame[] GetFrames(int count) { if (count < 0) { throw new ArgumentOutOfRangeException(nameof(count)); } if (count == 0) { return(Array.Empty <DbgStackFrame>()); } DbgStackWalker?stackWalker = null; try { stackWalker = CreateStackWalker(); var frames = stackWalker.GetNextStackFrames(count); Debug.Assert(frames.Length <= count); return(frames); } finally { stackWalker?.Close(); } }