How to prevent the debugger from calling some sour

2019-05-11 00:48发布

问题:

In visual studio, when an application is stopped during debug mode you can hover over an object/property to see whats inside of it.

When you open up an object using the debugger like I did with the above picture, the property has it's Get method called as a way for the debugger to retrieve the value of the property to show the user.

class Program
{
        static void Main(string[] args)
    {
        Foo foo = new Foo();

        foo.MyLock.EnterWriteLock();
        foo.Bar = 5.1;
        foo.MyLock.ExitWriteLock();

        // "I stop here and attempt to see what the value of Bar is via the debugger."
        foo.MyLock.EnterReadLock();
        Console.WriteLine(foo.Bar);
        foo.MyLock.ExitReadLock();
    }
}

class Foo
{
    private double bar;
    public double Bar 
    {
        get
        {
            Console.WriteLine(MyLock.IsReadLockHeld);
            Debug.Assert(MyLock.IsReadLockHeld, "Please enter the read lock before attempting to read this property.");
            return bar;
        }
        set
        {
            Debug.Assert(MyLock.IsWriteLockHeld, "Please enter the write lock before attempting to write this property.");
            bar = value;
        }
    }

    public ReaderWriterLockSlim MyLock { get; set; }

    public Foo()
    {
        MyLock = new ReaderWriterLockSlim();
    }
}

In my application I add in a Debug.Assert() call into my Get accessors to make sure that Foo in this example has been locked. Whenever my code called Bar, foo should be locked as per design, however when the debugger attempts to view bar, foo won't be locked which means the assert should fail.

When the debugger encounters an assert that fails it will sometimes suppress the assert popup and other times it will show the assert pop-up as per normal failed assert behavior. As best as I can tell the Assert popup appears to be suppressed for the first 1-2 times the debugger views the value of Bar but every time after those first 1-2 the popup is allowed to show. While this is the most common behavior of the assert suppressing this is not always the case because on other runs of the application the debugger never stopped suppressing no matter how many times the debugger viewed Bar.

Question: For my application the desired behavior would be for the asserts to be suppressed 100% of the time. How do I achieve this?

Edit: Also, if it helps when the debugger hits one of the asserts and it fails the below message it written to the Debug output. This is the exact same message regardless of whether or not the assert is suppressed.

---- DEBUG ASSERTION FAILED ----
---- Assert Short Message ----
Please enter the read lock before attempting to read this property.
---- Assert Long Message ----

   at TestApp_Debugging.Foo.get_Bar() in c:\Users\Adrian.vanBerkhout\Documents\Visual Studio 2013\Projects\TestApp_Debugging\TestApp_Debugging\Program.cs:line 37
   at TestApp_Debugging.Program.Main(String[] args) in c:\Users\Adrian.vanBerkhout\Documents\Visual Studio 2013\Projects\TestApp_Debugging\TestApp_Debugging\Program.cs:line 17
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

回答1:

I found a solution here. Decorate your problem properties with the DebuggerBrowsable attribute.

[DebuggerBrowsable(DebuggerBrowsableState.Never)]

Ideally you'd never need to do this. However, we have some properties that trigger a code contract exception when evaluated (in debug), which causes Visual Studio to get very confused. You probably need to decorate both the property on the class and any interface it implements.