4

I've inherited a project that, when started in debug, throws somewhere in the avenue of 8-10k NotImplementedExceptions. Because of this, the application takes over a minute to start when debugging... Every. Single. Time.

I talked to the original devs of the project and their solution to the issue is "Just press Ctrl+F5 to start without attaching a debugger". Apart from that being one of the worst solutions to a problem in the history of development, it does work and the application starts immediately. I'm trying to learn this new code-base so just skipping the debugger isn't an option for me.

Obviously I'm aware that no application should start with 10 thousand exceptions, but before I even get to fixing that I have to be able to debug the program.

I would like to suppress or skip first chance exceptions in the same way that starting without the debugger attached does. I've looked at this thread and applied the [DebuggerNonUserCode] attribute to the related methods but it only prevented the exceptions from being written to the output window. The program still takes over a minute to start up. Is this possible?

Edit:

I forgot to mention, I don't have anything checked in the Debug->Exceptions window. Also, all of the exceptions are wrapped in Try.. Catch statements

Community
  • 1
  • 1
Brandon
  • 4,491
  • 6
  • 38
  • 59
  • 1
    What's the practical problem with attaching the debugger after the app has launched? – Jon Mar 10 '14 at 15:38
  • Right-click the Output window, untick "Exception messages". It will help, a true cure would be *strongly* advisable. – Hans Passant Mar 10 '14 at 15:40
  • I need to debug/watch the code that's being executed while the application is starting up. This is where the exceptions are being thrown. Essentially: Before the form is even shown, 10k exceptions are raised. – Brandon Mar 10 '14 at 15:40
  • @HansPassant I assume this is the same as having the [DebuggerNonUserCode] attribute applied to the associated classes? It does help but only saves me a few seconds. – Brandon Mar 10 '14 at 15:46
  • Which version of Visual Studio are you using? I had a [similar experience with Visual C# 2010 Express](http://stackoverflow.com/questions/20555615/visual-c-sharp-2010-express-extremely-slow-exception-handling-from-debugger). The slowdown is strange especially if you've disabled the `NotImplementedException`. Have you tried [disabling extensions](http://stackoverflow.com/a/5463454/1174169)? – cod3monk3y Mar 10 '14 at 15:49
  • I'm using VS 2010 Ultimate. Your issue wasn'tquite the same problem as me (I have other applications that run perfectly), but that sounds like a nightmare. – Brandon Mar 10 '14 at 15:51
  • What about if you try this: Go to Debug | Exceptions, then expand the "Common Language Runtime Exceptions" item. Locate and expand `System`. Locate `System.NotImplementedException`. Ensure "Thrown" is not ticked (and maybe also "User-unhandled" is not ticked, although I'd have thought that wouldn't be necessary) – Matthew Watson Mar 10 '14 at 15:55
  • For sure, I just remember coming across several topics while I was diagnosing my problem that might help you. (see my edit above about extensions). Also have you tried disabling the Visual Studio Hosting process? – cod3monk3y Mar 10 '14 at 15:55
  • 1
    Out of curiousity, how are all these non-implemented methods being called and exceptions subsequently caught, presumably? NotImpl is mostly used for stubbing out new functionality during development or else meant to be passed on to a calling client to signal that some functionality really isn't available. – 500 - Internal Server Error Mar 10 '14 at 16:00
  • And...! Have you tried cloning the code base and hacking out parts of the code base to isolate the problem? I realize that 8-10k exceptions is poor coding practice, but you haven't mentioned a scenario in which the application *doesn't* take a minute to start up. So are you sure it's the exceptions that are causing the slow start-up? Can you recreate a minimal test application for us? – cod3monk3y Mar 10 '14 at 16:00
  • @MatthewWatson There are no boxes checked in that window at all. Even user-unhandled. All of the exceptions actually are user-handled though. – Brandon Mar 10 '14 at 16:05
  • @cod3monk3y I haven't disabled the hosting process. I've never done it before, will it still allow me to debug? My scenario for the application not taking a minute to start up is just running it without a debugger. There is no other way to avoid the exceptions, they occur every time. – Brandon Mar 10 '14 at 16:06
  • @500-InternalServerError When I asked the original developer, he said they're there on purpose because he had abstracted a class, inherited from it and had a bunch of child instances that don't/can't implement the abstracted functionality. I know that this is horrible design. He said the NotImpl's are there to prevent him from calling into those methods accidentally... Which obviously went to the dogs. – Brandon Mar 10 '14 at 16:08
  • 1
    The `NotSupportedException` was created for that reason, though I suspect it wouldn't change anything in regards to your problem, just wanted to point that out. – julealgon Mar 10 '14 at 16:10
  • @julealgon Yes it was. One or two I could understand, but he's calling into the methods thousands of times anyway because everything is abstracted/virtual. – Brandon Mar 10 '14 at 16:12
  • Perhaps you need to look at why you're making 10k calls at startup. See my analysis below on the timing of 10k calls *even without exceptions*. – cod3monk3y Mar 10 '14 at 16:18
  • (oops.. my bad. I wasn't resetting the timer. I should go get some coffee) – cod3monk3y Mar 10 '14 at 16:24
  • The 10k+ calls are being made because it's recursively loading a very large XML file. The file and code to load the file is legitimate. – Brandon Mar 10 '14 at 16:28
  • Would a possible work-around be to run the XML load in a `Task` and then `Dispatcher.BeginInvoke` the loaded object back to the main thread? Could be a possible workaround, or general improvement to load-up time in all scenarios. – cod3monk3y Mar 10 '14 at 16:33
  • That could be a solution but it would involve me breaking out the code to load the XML, which is deeply coupled with the functional code for the application (this just keeps getting better, I know). – Brandon Mar 10 '14 at 16:51

2 Answers2

4
  1. Check your Visual Studio settings under Debug -> Exceptions -> Common Language Runtime Exceptions -> System -> System.NotImplementedException and make sure that Thrown is NOT checked. (it should be not checked by default, but this would cause it to stop even if exception were to be handled).
  2. Crappy workaround: In the part of the code which is past all exceptions, where you want to start debugging, put the following lines

    System.Diagnostics.Debugger.Launch();
    System.Diagnostics.Debugger.Break();
    

You can then start Ctrl+F5, and then be prompted to attach debugger when it hits that point in the code.

LB2
  • 4,802
  • 19
  • 35
  • Unbelievable... your crappy workaround is pretty much what I was looking for actually. I was able to launch the debugger immediately after starting execution and after the exception throwing lines. Some properties of some objects don't produce results properly but I can deal with that. Awesome. – Brandon Mar 10 '14 at 17:34
  • @Brandon By the way, just `.Launch` or just `.Break` may be enough (i.e. just one of them), but I couldn't remember for sure so I put both. If debugging causes you to break twice here, you may be able to remove one of them. – LB2 Mar 10 '14 at 17:36
  • 1
    Yeah I caught on to that actually and just used `.Launch`. Thanks! – Brandon Mar 10 '14 at 17:39
  • Then I get System is not defined. – user2568374 Aug 30 '19 at 00:47
  • @user2568374, if you get `System` not defined, then something is very wrong with VS/.NET installation. What about referencing anything else in `System` namespace? – LB2 Aug 30 '19 at 15:02
  • Thanks but not sure this is very old code written in vs2010. Its for an ActiveX control. I found I could debug by putting message box in code and when it hits it attach to browser then. – user2568374 Sep 01 '19 at 01:05
0

EDIT: Major edit to remove my early-morning brain damage.

To provide some additional info for my point, to try to show steps that can be used to reduce the startup time for this number of exceptions. This code allows me to profile N calls with or without the exception being thrown:

void Run(int n, bool doThrow, bool doExcept)
{
    for (int i = 0; i < n; i++)
    {
        if (doExcept)
        {
            try
            {
                if (doThrow)
                    throw new NotImplementedException();
            }
            catch (NotImplementedException)
            {
            }
        }
    }
}

The testing scenario gives the following numbers when no checkmarks are set in the Exceptions dialog, in Debug mode with the VS hosting process.

1; 4.000 msec
1: 0.000 msec (no throw)
1: 0.000 msec (no throw, no except)
10; 32.000 msec
10: 0.000 msec (no throw)
10: 0.000 msec (no throw, no except)
100; 780.000 msec
100: 0.000 msec (no throw)
100: 0.000 msec (no throw, no except)
1000; 7251.000 msec
1000: 0.000 msec (no throw)
1000: 0.000 msec (no throw, no except)
10000; 35694.000 msec
10000: 0.000 msec (no throw)
10000: 0.000 msec (no throw, no except)

So clearly the number of exceptions is what matters here, as you expected. I'll edit with some more numbers from different scenarios in a minute.

In debug with the VS hosting process, the exceptions take about 3.5-7 msec. Disabling the VS hosting process (which still allows debugging) in debug mode drops the time down to 1.9 msec per exception:

1; 3.000 msec
10; 21.000 msec
100; 198.000 msec
1000; 1917.000 msec
10000; 19065.000 msec

And release mode without the VS hosting process takes about 1.8 msec (edit after plugging in my laptop):

1; 3.000 msec
10; 17.000 msec
100; 184.000 msec
1000; 1823.000 msec
10000; 18248.000 msec

And running in release mode outside of the debugger is about 0.016 msec per exception:

1; 1.000 msec
10; 1.000 msec
100; 3.000 msec
1000; 19.000 msec
10000; 138.000 msec

So in my test setup, it still doesn't load "instantly" from the debugger with 10k exceptions in release. Though, this could be related to the problems I experienced before with my 2010 installation (I've since reinstalled). It does load extremely quickly outside of the debugger.

Here is my full testing rig:

static void Main(string[] args)
{
    Stopwatch sw = new Stopwatch();
    var p = new Program();

    int[] tests = new int[] { 1, 10, 100, 1000, 10000 };
    foreach (int n in tests) {
        sw.Start();
        p.Run( n, true, true);
        sw.Stop();
        Console.WriteLine(string.Format("{0}; {1:0.000} msec", n, sw.ElapsedMilliseconds));

        sw.Start();
        p.Run(n, false, true);
        sw.Stop();
        Console.WriteLine(string.Format("{0}: {1:0.000} msec (no throw)", n, sw.ElapsedMilliseconds));

        sw.Start();
        p.Run(n, false, false);
        sw.Stop();
        Console.WriteLine(string.Format("{0}: {1:0.000} msec (no throw, no except)", n, sw.ElapsedMilliseconds));
    }

    Console.WriteLine("Any key to exit...");
    Console.ReadKey();
}
cod3monk3y
  • 9,508
  • 6
  • 39
  • 54