Debugging multi-threaded operations problem

You'll love this one...

I've ran into a rather odd problem, both in the application I'm in the process of developing and in a test project I threw together just to replicate the issue.

When debugging code that is run on a thread other than the main execution thread the non-main thread will exit for no apparent reason. Here's the kicker... It only happens if you have the autos variable window selected i.e. the problem will not show if you're viewing the watch list.

Here's how to replicate:

Visual Studio 2005 Standard 8.0.50727.42

1 Create a new Windows Application for C#.
2 Create 1 button.
3 Use the following for your class code.
public partial class Form1 : Form
    {
        Thread thread = null;
        ThreadStart ts = null;
        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ts = new ThreadStart(myfunc);
            thread = new Thread(ts);
            thread.Name = "MyThread";

            thread.Start();
        }

        protected void myfunc()
        {
            int jj = 0;
            for (int i = 0; i < 100; i++)
            {
                jj += i;
                Thread.Sleep(1000);
            }
        }
    }

4 Set a breakpoint on the jj += i; line
5 Start debugging the application
6 Click the button1
7 Wait for a long time while System.Configuration dll to load...
8 Make sure you have the Autos window open
8 Hit F10 to step over
9 Watch your thread exit in the output window...
10 Stop debugging
11 Restart debugging
12 Click the button1
13 etc
14 Make sure you are not viewing the Autos window (switch to Watch 1 or something)
15 Hit F10 to step over
16 Ponder why in the world this made any difference.
17 Submit problem to forum
18 Type this message...

Anyone have any ideas on this

Thanks,
Scott


Answer this question

Debugging multi-threaded operations problem

  • boris_skarbo

  • Bernard C

    > Yeah, watching "this" it seems like the this.button1 is throwing the eval timeout.

    In my case it is the form that has timed out, button1 only reports that is was not evaluated because previous evaluation timed out.

    > That might be for step 7. However if you watch the output window, right before
    > the ui for the debugger regains control (i.e. you can move the cursor around) the
    > "loaded system.configuration.dll" message shows up, and then you regain control.

    The delay will still remain even if, for testing purposes, I load system.configuration.dll before the breakpoint is hit.

    > I don't know how you are figuring that an exception is being thrown, but it
    > sounds believable. I've looked for evidence that an exception is being thrown but > cannot find any.

    I monitored the debuggee with a native debugger (WinDbg).

    > Either way. The whole problem here is this behavior, for whatever reason, is
    > inconsistant and/or different than VS2003. I've create this exact program in
    > VS2003 and have no problems (or long pauses).

    It looks like the debugger's behavior is consistent between two versions (VS2003 and VS2005). When it is doing func-eval and hijacks a thread for that purpose, it suspends all other managed threads. Therefore all func-evals that need thread context switch will not be able to complete and will time out. For example, you can try to evaluate WindowText property of any control (e.g. button1) in the worker thread and see it timing out in VS2003 debugger. After that, the worker thread will terminate with even more obvious symptoms than in VS2005.

    The difference seems to be in the debugging-related configuration of the involved classes. Form class in VS2005 is configured to include (and therefore evaluate) its Text property in the output in Auto/Watch window, while in VS2003 it does not do that. If you change, for example, mcee_cs.dat in VS2003 to display Text property for your form class (e.g. in a way similar to the standard Button class in the same file), you will see the timeout again in VS2003.

    On the contrary, if DebuggerDisplay attribute is used to disable func-eval on the form class in VS2005, the timeout does not happen. Something like:
    [DebuggerDisplay("Do not funceval")]
    class Form1 : ...

    > Even if the behaviour we're seeing is by design, or a side-effect of the new
    > debugger, it seems ridiculous that such a simple multi-thread program cannot be
    > debugged (using a fresh, default installation of vs2005), and either a fix should
    > be made, or some instructions should be given on how to fix/stop it.

    Gregg's blog entry gives three workarounds :)

    Oleg

  • trianta99

    Yeah, watching "this" it seems like the this.button1 is throwing the eval timeout.

    That might be for step 7. However if you watch the output window, right before the ui for the debugger regains control (i.e. you can move the cursor around) the "loaded system.configuration.dll" message shows up, and then you regain control.

    I don't know how you are figuring that an exception is being thrown, but it sounds believable. I've looked for evidence that an exception is being thrown but cannot find any.

    Either way. The whole problem here is this behavior, for whatever reason, is inconsistant and/or different than VS2003. I've create this exact program in VS2003 and have no problems (or long pauses).

    Even if the behaviour we're seeing is by design, or a side-effect of the new debugger, it seems ridiculous that such a simple multi-thread program cannot be debugged (using a fresh, default installation of vs2005), and either a fix should be made, or some instructions should be given on how to fix/stop it. I not angry or anything I just want to adequelty relay my fustration with how much time I've spent on the subject. If the problem is by design I'd just like to know that. Big Smile

    Thanks,
    Scott


  • Terry Rossow

    I turned that option off. At least now the thread doesn't immediately crash out. However, when debugging a slightly more complicated multi-threaded form with a label, when I expand the properties for that label in the autos window, it works until it reaches preferredheight whose value reads "Function evaluation timed out."; and then the thread exits upon F10.

    I also tried disabling "Enable property evaluation and other implicit function calls", which does stop the thread from crashing, however it makes the debugger relatively useless. I'm not trying to be a pain here, but this behavior really is different than VS2003.

    Scott


  • StephaneB

    Hi -
    I've moved this thread to the Visual Studio debugger forum.  They should be able to help you here.

    Thanks!
    Karen

  • blkeller

    The object whose ToString causes this behavior is the form itself, "this".
    Also, it seems that the delay in step 7 is actually the timeout when the debugger is waiting for the func-eval to complete (if you expand "this", there probably will be a message that the previous func-eval has timed out).

    Also it seems that after F10 an exception is thrown in the debuggee (probably during the next func-eval), which causes the thread to exit.

    Regards,
    Oleg

  • DataCorrupt

    > The difference seems to be in the debugging-related configuration of the
    > involved classes.

    No, here I was wrong. The difference is that VS2005 debugger by default calls ToString() in Auto/Watch window to evaluate objects whose types do not have DebuggerDisplay attribute. Form's ToString needs a thread switch, and thus times out.

    It can be disabled (and VS2003-like behavior restored) by unchecking this option:

    Tools | Options | Debugging | General | "Call ToString() on objects in variables windows (C# only)".

    Oleg


  • AEnglish

    Thanks... Hopefully someone will be able to figure this one out :)

  • maui_desu

    That makes sense, however I don't beleive there are any objects whose ToString() function, or any other property would cause this unusual behavior.  With the example code being so simple I don't think there's any room for what you're suggesting to be the cause.

    Anyone else care to test this out on their system I've duplicated now on two seperate machines.

    Thanks,
    Scott

  • ascanio

    This sounds like a fun issue... I'm going to give this a try when I get home.


  • Debugging multi-threaded operations problem