Looks like many people liked my macros that made multithreaded debugging easier. One of the comments on the article from Sam was worth exploring deeper:

John,
Great post!
Would you have any idea how to make VS do this: http://stackoverflow.com/questions/837869/is-there-a-shortcut-in-vs-for-next-statement-in-current-thread

This very common problem comes up the more threads you have. The gist of the problem is that you’re stepping one thread, but all of a sudden, you’re stepping a completely different thread. What’s happening is that the thread your stepping is getting it’s time slice, but your other threads are not so the thread scheduler pulls the thread you’re stepping off the CPU and puts a starving thread on. Hence, it looks like you are bouncing around threads.

The solution proposed in the Stack Overflow question is to freeze the other threads, which is about all you can do. Once stopped in the debugger, open the Threads window and right click on the thread you don’t want to run and select Freeze from the context menu.

In the above screen shot, I already froze thread ID 5788, which is shown by the pause icon in the far left column and the Suspend column has a count of 1. Note that the suspend count could be higher if your code has called Thread.Suspend/SuspendThread on the thread. If you want to freeze multiple threads from the debugger at the same time, hold down the control key and click to multi select. The context menu Freeze works on all selected threads.

That’s great that you can freeze threads like this. However, could you possibly screw up your application doing so? Absolutely! If you’re doing mixed .NET and native debugging and you suspend the garbage collector thread, let’s just say your garbage collections might take approximately forever to finish. Freezing threads is a very powerful technique, but one to use carefully. Many times all you want to do is ensure you step through the end of the current function without bouncing to another thread so freezing all the other threads probably won’t cause any problems as long as you thaw them before you return.

If you have only two threads in your application, it’s easy to freeze the other thread. It gets more tedious if you have many threads in your application. (If you think you have a bunch now, wait until we are all using the new Parallel Task Library coming up in .NET 4.0.) When I’m debugging and want to freeze threads, I always seem to be suspending all the other threads in the program except the active one. As I’m too lazy to manually select all those other threads, I automated thread freezing and thawing with the FreezeAllButActiveThread and ThawAllFrozenThread macros below for your enjoyment. Note that the Threads window sometimes doesn’t update after running these macros to show the new state.

Is there anything else you want to see automated while debugging? How about with Visual Studio itself? If so, ask away in the comments or send me an email. Consider me your personal developer! <grin>

 

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Wintellect Debugging Code
' Copyright © 1997-2009 John Robbins
            -- All rights reserved. 
' Freeze and thaw threads in bulk.
'
' Version 1.0 - July 17, 2009
' - Initial version. 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics
Imports System.Text
Imports System.Collections.Generic
Imports System.Runtime.InteropServices
Imports System.Windows.Forms

Public Module FreezeThawThreads

    Public Sub FreezeAllButActiveThread()

        Dim dbg As EnvDTE90.Debugger3 = DTE.Debugger
        If dbg.CurrentMode = dbgDebugMode.dbgBreakMode Then
            Dim currProg As Program = dbg.CurrentProgram
            For Each t As Thread2 In currProg.Threads
                If (t.ID <> dbg.CurrentThread.ID) Then
                    If t.IsFrozen = False Then
                        t.Freeze()
                    End If
                End If
            Next
        Else
            NotInBreakMode()
        End If

    End Sub

    Public Sub ThawAllFrozenThreads()
        Dim dbg As EnvDTE90.Debugger3 = DTE.Debugger
        If dbg.CurrentMode = dbgDebugMode.dbgBreakMode Then
            Dim currProg As Program = dbg.CurrentProgram
            For Each t As Thread2 In currProg.Threads
                If t.IsFrozen = True Then
                    t.Thaw()
                End If
            Next
        Else
            NotInBreakMode()
        End If
    End Sub

    Private Sub NotInBreakMode()
        MessageBox.Show(New MainWindow(), _
                        "You must
            be stopped in the debugger for this macro to work", _
                        "Wintellect
            Thread Freeze/Thaw Macros", _
                        MessageBoxButtons.OK, _
                        MessageBoxIcon.
            Error)
    End Sub

    ' A helper class so I can parent
            message boxes correctly on the IDE.
    Class MainWindow
        Implements IWin32Window

        Public ReadOnly Property Handle() _
                            As System.IntPtr Implements IWin32Window.Handle
            Get
                ' The HWnd property
            is undocumented.
                Dim ret As IntPtr = CType(DTE.MainWindow.HWnd, IntPtr)
                Return (ret)
            End Get
        End Property
    End Class

End Module