11

When running my application, I found exception log below in Output panel of Visual Studio.

A first chance exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll

This application's architect is as follows.

  • Second thread: Enqueue "add item to listview" or "change item to listview" command into a queue.
  • Main thread: Dequeue from a queue and execute add or change operation defined by each command.

I want to know details of InvalidOperationException called from, but it's only shown on Output panel, so I can't catch it for viewing stack trace. Is there a way to know it?

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
kobake
  • 1,091
  • 1
  • 12
  • 15
  • Wrap the whole application in a `try`/`catch`? Run it in the debugger with it set to break on every exception? – Bobson Jul 02 '13 at 17:45
  • 1
    Set try / catch in whole of Program.Main, but it can't catch InvalidOperationException. – kobake Jul 02 '13 at 17:47
  • 2
    Go to `Debug -> Exceptions...` and check off the `Thrown` option next to `Common language Runtime Exceptions`. – Bobson Jul 02 '13 at 18:06
  • Thanks!!! I did exception setting and I got details of the exception! Details are got by visual studio dialog which is shown after changing exception setting. I still can't catch the exception but my aim is reached. – kobake Jul 02 '13 at 18:30
  • I'd guess that you are forgetting to protect the queue with a lock. Required to prevent the worker thread from modifying the queue while the main thread is iterating it. Don't catch exceptions willy-nilly, that will just make your code fail in an undiagnosable way. – Hans Passant Jul 02 '13 at 18:33
  • OK, I'll take care of it. A queue is thread safe. – kobake Jul 02 '13 at 18:38
  • Details of the exception I could get is that "When in VirtualMode the ListView RetrieveVirtualListItem event needs a list view SubItem for each ListView column." – kobake Jul 02 '13 at 18:41
  • @kkoba - I turned that comment into an answer. – Bobson Jul 02 '13 at 18:57

3 Answers3

28

The best way to find where an exception like this is being triggered is to set the debugger to break on all exceptions.

You can do this by going to the Exception Settings window and checking the checkbox next to Common Language Runtime Exceptions under 'Break When Thrown'.

If you don't see the Exception Settings window, you can open it from the top menu at Debug -> Windows -> Exception Settings (there's also a keyboard shortcut of Ctrl+Alt+E to open it.

This will break anytime a .NET exception is thrown, regardless of where or whether it's handled.

This won't fix your problem, but it'll help identify it.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Bobson
  • 13,498
  • 5
  • 55
  • 80
3

Use a try/catch like this:

try
{
   //Some code here.
   //Also, set your breakpoints here.         
}

catch (InvalidOperationException exc)
{
   MessageBox.Show(exc.ToString());
}

catch (Exception exception)
{
   MessageBox.Show(exception.Message);
}

Exception handling in C# (and other languages) goes from the most specific exception to the least specific exception type. The above example will show the stack trace in a MessageBox as well.

Brian
  • 5,069
  • 7
  • 37
  • 47
  • 1
    As you suggest, I set catch(InvalidOperationException) into all of try/catch block, but application doesn't reach it... – kobake Jul 02 '13 at 18:05
1

Try doing the following:

  1. Add a breakpoint in the necessary location
  2. Right-click on the breakpoint and click "When hit.."
  3. Check the "Print a message" box, and use the tokens that they show to display the information that you want (e.g., calling funciton, stacktrace, thread ID/name, process ID/name, etc.)
  4. If you want the program to continue execution after printing the message (i.e. you do not want it to pause on the breakpoint), also check the "Continue Execution" box


You will likely want to combine this technique with a try/catch, as has been suggested by others. I do not want to repeat code provided in others' answers, but I would use Brian's try/catch to wrap your calls, and then set the breakpoints using this technique.


Note: You can also use this technique and the "breakpoint conditions" to call methods (i.e., print results) and/or change values (the latter is a bit of a hack, though, and should only be done if it is completely necessary and you are working on a 64-bit application). These additional features may or may not also be of use to you in this situation.

Zachary Kniebel
  • 4,686
  • 3
  • 29
  • 53
  • 1
    Thanks, but I can't decide good place to add a breakpoint because I don't know where the exception caused from. – kobake Jul 02 '13 at 18:00
  • If that is the case, I would set up a few breakpoints that print out the current executing function's name (`$FUNCTION` is the token) and set the "Continue execution" box to true. Set them up in places before and after where you think the exception occurred and then narrow your search from there (think of a binary search, only with breakpoints). – Zachary Kniebel Jul 02 '13 at 19:25