调试多线程更方便的两个特性(让断点只在特定线程触发、同时查看所有线程的堆栈信息)

John Robbin 写了一篇博客,说是有人抱怨VS2008对多线程调试支持的不好,不支持他最希望看到的两个功能:1)多线程时调试时可以同时查看所有线程的堆栈信息;2)不允许设置断点只在特定的线程上触发,而不在其它的线程上触发. 对此john robbin 给出了它的答案,第一个功能vs2008本身无法实现,在vs2010中的Parallel Stacks window窗口可以实现这个功能;[其实我倒知道名叫"debuginspector"的vs addin 可以实现同时在vs2008中同时查看所有线程堆栈信息的功能.] 针对第二个功能,john robbin通过编写macro的方式给出了答案,下面是macro的代码:

代码
1 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
2  ' InterestingThread - John Robbins (c) 2009 - john@wintellect.com
3 ' A set of macros that make debugging multithreaded programs easier.
4 '
5 ' Version 1.0 - July 11, 2009
6 ' - Initial version.
7  '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
8  Imports System
9  Imports EnvDTE
10 Imports EnvDTE80
11 Imports EnvDTE90
12 Imports System.Diagnostics
13 Imports System.Text
14 Imports System.Collections.Generic
15 Imports System.Runtime.InteropServices
16 Imports System.Windows.Forms
17
18 Public Module InterestingThread
19 ' The caption for all message boxes.
20 Private Const captionTitle As String = "Wintellect Interesting Thread Macros"
21 ' The Filter set on breakpoints.
22 Private Const k_THREADFILTER As String = "ThreadName == InterestingThread"
23 ' For all breakpoints, sets the Filter to "ThreadName == InterestingThread"
24 Public Sub SetAllBreakpointsToInterestingThreadFilter()
25 Dim currBP As EnvDTE80.Breakpoint2
26 For Each currBP In DTE.Debugger.Breakpoints
27 ' Only set the filter if it's empty.
28 If (String.IsNullOrEmpty(currBP.FilterBy) = True) Then
29 currBP.FilterBy = k_THREADFILTER
30 End If
31 Next
32 End Sub
33 ' For all breakpoints, clears the Filter if it's set to
34 ' "ThreadName == InterestingThread"
35 Public Sub ClearAllBreakpointInterestingThreadFilters()
36 Dim currBP As EnvDTE80.Breakpoint2
37 For Each currBP In DTE.Debugger.Breakpoints
38 If (String.Compare(currBP.FilterBy, k_THREADFILTER) = 0) Then
39 currBP.FilterBy = String.Empty
40 End If
41 Next
42 End Sub
43 ' Sets a breakpoint on the current source code line with the Filter set
44 ' to "ThreadName == InterestingThread"
45 Public Sub SetInterestingThreadBreakpoint()
46 ' There has to be a document open for things to work.
47 Dim currDoc As Document = GetCurrentDocument()
48 If (currDoc Is Nothing) Then
49 Exit Sub
50 End If
51 ' Get the cursor location. I'll make my setter behave the same
52 ' way as when you have a selection and press F9, which will
53 ' set a breakpoint on the top part of the selection. However,
54 ' unlike F9 breakpoints, I won't clear the selection after
55 ' setting the breakpoint.
56 Dim txtSel As TextSelection = CType(currDoc.Selection, TextSelection)
57 Dim point As VirtualPoint = txtSel.TopPoint
58 Try
59 Dim bps As EnvDTE.Breakpoints = DTE.Debugger.Breakpoints.Add( _
60 File:=currDoc.FullName, _
61 Line:=point.Line, _
62 Column:=point.DisplayColumn)
63 ' There's no way to set the filter property when adding a
64 ' breakpoint so you have to do it after the file and line
65 ' breakpoint is set.
66 Dim newBP As EnvDTE80.Breakpoint2
67 For Each newBP In bps
68 newBP.FilterBy = k_THREADFILTER
69 Next
70 Catch ex As COMException
71 ErrorMessage(ex.Message)
72 End Try
73 End Sub
74 Private Function GetCurrentDocument() As Document
75 ' Check to see if a project or solution is open. If not, you
76 ' can't get at the code model for the file.
77 Dim projs As System.Array = CType(DTE.ActiveSolutionProjects, Array)
78 If (projs.Length = 0) Then
79 ErrorMessage("You must have a project open.")
80 GetCurrentDocument = Nothing
81 Exit Function
82 End If
83 ' Getting the active document is a little odd.
84 ' DTE.ActiveDocument will return the active code document, but
85 ' it might not be the real ACTIVE window. It's quite
86 ' disconcerting to see macros working on a document when you're
87 ' looking at the Start Page. Anyway, I'll ensure the active
88 ' document is really the active window.
89 Dim currWin As Window = DTE.ActiveWindow
90 Dim currWinDoc As Document = currWin.Document
91 Dim currDoc As Document = DTE.ActiveDocument
92 ' Gotta play the game to keep from null ref exceptions in the
93 ' real active doc check below.
94 Dim winDocName As String = String.Empty
95 If Not (currWinDoc Is Nothing) Then
96 winDocName = currWinDoc.Name
97 End If
98 Dim docName As String = "x"
99 If Not (currDoc Is Nothing) Then
100 docName = currDoc.Name
101 End If
102 If ((currWinDoc Is Nothing) And _
103 (winDocName <> docName)) Then
104 ErrorMessage("The active cursor is not in a code document.")
105 GetCurrentDocument = Nothing
106 Exit Function
107 End If
108 ' While I might have a document, I still need to check this is
109 ' one I can get a code model from.
110 Dim fileMod As FileCodeModel = _
111 currDoc.ProjectItem.FileCodeModel
112 If (fileMod Is Nothing) Then
113 ErrorMessage("Unable to get code model from document.")
114 GetCurrentDocument = Nothing
115 Exit Function
116 End If
117 GetCurrentDocument = currDoc
118 End Function
119 Private Sub ErrorMessage(ByVal text As String)
120 MessageBox.Show(New MainWindow(), text, captionTitle, MessageBoxButtons.OK, MessageBoxIcon.Error)
121 End Sub
122 ' A helper class so I can parent message boxes correctly on the IDE.
123 Class MainWindow
124 Implements IWin32Window
125 Public ReadOnly Property Handle() As System.IntPtr Implements IWin32Window.Handle
126 Get
127 ' The HWnd property is undocumented.
128 Dim ret As IntPtr = CType(DTE.MainWindow.HWnd, IntPtr)
129 Return (ret)
130 End Get
131 End Property
132 End Class
133 End Module
134

原文链接:http://www.wintellect.com/CS/blogs/jrobbins/archive/2009/07/13/easier-multithreaded-debugging.aspx?CommentPosted=true#commentmessage

PS:推荐各位请阅john robbin’s blog,另外他的著作<microsoft .net 2.0应用程序调试>也不错,不光详细的介绍了.net应用程序的调试,也随书附带了很多实用性的工具.

原文地址:https://www.cnblogs.com/zhangronghua/p/VSMutilThreadDebugMacro1.html