System.Diagnostics.Debugger.Break() is a BCL method that causes a program to issue a User Breakpoint when run under the debugger.

This translates to a Break() debug event on ICorDebugManagedCallback. (Not to be confused with Breakpoint(), which corresponds to actual breakpoints. Yeah, we could have given them better names...)

The debugger will break at the callsite of the Break(), and not actually inside the call. This is convenient because it means that the caller is on top of the stack, which is what you'd intuitively expect. It also means that Debugger.Break() behaves almost identical to if you had manually set a breakpoint at the location and hit it.

There's also an IL 'break' opcode that does the same thing as Debugger.Break(). You can view Debugger.Break() as functional access to the break opcode. In both cases, it ends up as a call into the CLR engine which then does a few things:
- if no debugger is attached, it may cause a managed JIT-attach (similar to Debugger.Launch).
- if a debugger is attached, it will essentially do a step-out of the CLR engine's frames to get back to the call-site. This essentially gets the mscorwks frames off the stack.
- once that step out completes, it sends the user breakpoint event to the debugger.

 

Usages:

This can be useful in a variety of ways.

  1. This is the managed counterpart to kernel32!DebugBreak().  (See more comparison of managed vs. native debug methods)
  2. VB's 'stop' statement is implemented via Debugger.Break().  (JScript's 'debugger' statement could be implemented on this too).
  3. It's useful for assert dialogs or error checks.
  4. Strongly preferred way for instant break-into-the-debugger over exceptions.  Exceptions may modify your program's actual control flow. Debugger.Break() won't. It just notifies the debugger but has no other side-effects.

 

Quick demo:

Run this VB code:

Module Module1

    Sub Main()

        Console.WriteLine("Hi!")
        Stop
        Console.WriteLine("done")
    End Sub

End Module

And you stop in the debugger at the 'stop' statement. In the callstack you see:

>    ConsoleApplication2.exe!ConsoleApplication2.Module1.Main() Line 6 + 0x5 bytes    Basic
     [External Code]   

If you view the code in Reflector as C#, you see the Stop statement is Debugger.Break():
[STAThread]
public static void Main()
{
    Console.WriteLine("Hi!");
    Debugger.Break();
    Console.WriteLine("done");
}