If you ever try to debug a multi-threaded Windows Forms application, today's blog is for you. A customer asked me about this issue, and since I have also run into this problem, I decided to talk about it.

What is func eval?

If you already know what func eval is, or don't care, skip to the bottom.

For the rest of us, I wanted to give some background. Func Eval is short for 'function evaluation'. The idea is this: instead of just reading data out of the debuggee process to fill out the watch window, the debugger actually causes code to run inside the debuggee process. It does this by hijacking the stopped thread, and running something entirely different on that thread. Func eval has been a feature of the Visual Studio debugger for a while now.

Usually, func eval is a great feature. It makes it so easy to dig into variables that hold framework classes. You don't need to write a bunch of code to figure out what all the properties are returning, you can just look at all of them under the debugger.

The problem with func eval is that it is a double-edged sword: if your ToString implementation or your property-getter implementation does something 'bad', it can make it pretty much impossible to debug, because your code will act differently under the debugger.

To avoid problems with func eval, don't write complex property getters/ToString functions. If you need to do something complex, put it in a 'GetFoo' instead making Foo a property. If you decide to make your property complicated, mark it as never browsable:


        int Foo




                return 12;



Func eval and multithreading


System.Windows.Forms.Form and multithreading


Work around #1 -- Stop the debugger from calling ToString.


To do this you can override ToString -or- set a DebuggerDisplay attribute (see below) -or- uncheck 'Call ToString() on objects in variables windows (C# only)'.

Example of DebuggerDisplay attribute:


    public partial class Form1 : Form

Work around #2 -- Disable func eval entirely

Uncheck 'Enable property evaluation and other implicit function calls'. This solves the problem, but it may make debugging other things more difficult.

Work around #3 -- Avoid the problem



Feedback wanted
