3

I have a winform application. Every few seconds I check some log files, read in any new data and insert any new data into a DB.

When I run the application for around an hour 1/2, I get a StackOverflowException. There was no new data in the log files for that entire period, so nothing new was added to the DB.

The code errored here...

if (pictureBox == null)
{
    continue;
}

if (pictureBox.InvokeRequired)
{
    var toolTip = new ToolTip();
    GameServer tempGameFile = gameServer;
    pictureBox.Invoke(new MethodInvoker(
        () => toolTip.SetToolTip(pictureBox,
            string.Format(
                "{0} : Last Checked: {1}; Last Updated: {2}",
                tempGameFile.Name,
                tempGameFile.CheckedOn.ToLongTimeString(),
                tempGameFile.UpdatedOn.HasValue
                    ?
                        tempGameFile.UpdatedOn.Value.ToLongTimeString()
                        : "-No Date Set-"))));
}
pictureBox.Image = Resources.RedButton;

and the pictureBox.Invoke(..) is throwing that error.

So .. i'm not sure how I can bebug this to figure out what is going on? Any suggestions?

UPDATE

Trying the suggestions of Dmitry I've started an ANTS profiler memory profile .. and having a quick look at things .. there seems to be a lot of instances of ToolTip controls.

This is a class list summary after 20 mins.

enter image description here

Lots of EventHandlers (am I not releasing something?)

And there's a few ToolTips also...

Here is a screenshot of all the instances and here is a screenshot of a single ToolTip control graph/map .. which I don't know how to read blush

Community
  • 1
  • 1
Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
  • What is triggering the posted code? It doesn't include a method signature and isn't clear, at least not to me. – Samuel Neff Aug 29 '11 at 04:12
  • That's my problem Samuel -> i'm not sure either. That's where the application crashes, on the `pictureBox.Invoke(..)` method. I'm not sure if that's erroring or how I can confirm that? I'm wondering if i'm constantly Invoking but never cleaning up after myself, with that line? Otherwise do i need to get some other app to look at the instances that haven't been cleaned up (still have a rogue reference to them) or something ... ??? – Pure.Krome Aug 29 '11 at 04:15
  • 2
    Which event is that code placed in? – jgauffin Aug 29 '11 at 04:30
  • I've got the application running again .. need to wait an hour more or so before the SOE is thrown :( Now .. what event is that code placed in? It's a method that is called inside `GameServersParsingBackgroundWorker_DoWork` .. a `BackgroundWorker` process. – Pure.Krome Aug 29 '11 at 04:58
  • Hard to imagine this giving a SO error. Do you have nested eventhandlers and/or Application.DoEvents() elsewhere in your code? The fact that the error shows up here does not mean that it is caused here. – H H Aug 29 '11 at 09:36
  • Hmm ... possibly. Not sure.. as in, in eed to check. I've got ANTS memory profiler running (after making @Dmitry 's changes) .. and there's a frak load of ToolTip instances in memory...... – Pure.Krome Aug 30 '11 at 01:39
  • As mentioned above, the first thing you need to do is to obtain a stack trace when the exception happens. – Andrew Savinykh Aug 30 '11 at 02:06

2 Answers2

4

You have 2 potential issues with your code:

var toolTip = new ToolTip();

and

pictureBox.Image = Resources.RedButton;

are both called on non-UI thread. I have to marshal this code to UI thread using Control.Invoke. If fixing this does not help, look at my answer on how to debug StackOverflowException in windows service.

UPDATE: try this code. Note that every statement that references any UI control needs to be marshaled using Control.Invoke:

if (pictureBox == null || !pictureBox.IsHandleCreated) {
    continue;
}

Action setTooltipAndImage = () => {
    var toolTip = new ToolTip();
    GameServer tempGameFile = gameServer;
    toolTip.SetToolTip(pictureBox, string.Format(...));
    pictureBox.Image = Resources.RedButton;
};

if (pictureBox.InvokeRequired) {                        
    pictureBox.Invoke(setTooltipAndImage);
} else {
    setTooltipAndImage();
}

It might worth reading Manipulating Controls from Threads.

Community
  • 1
  • 1
Dmitry
  • 17,078
  • 2
  • 44
  • 70
  • So I need to `Invoke` both of those? Right now i'm doing that for the `SetToolTip` .... but that's not enough? Can u provide some sample code? You're 100% right that i'm accessing these UI elements from a background thread. – Pure.Krome Aug 29 '11 at 04:57
  • Access to modified closure for: `GameServer tempGameFile = gameServer;` so I just made a temp copy above the `Action setToolTipAndImage ...` code .. ie. `var tempGameServer = gameserver; Action setToolTipAndImage ... ` Also, my original code was not Invoking -all- the things with a toolTip .. so i needed to Invoke both the `new`, `SetToolTip` and `Resources.RedButton`. Gotcha. – Pure.Krome Aug 29 '11 at 06:27
  • I'm running ANTS memory profiler and seeing bucket loads of ToolTip instances in memory. Is it worth posting an image of a graph/map of one of these instances .. so see where's it's keeping a handle on? – Pure.Krome Aug 30 '11 at 01:41
  • @Pure.Krome: might be worth not creating as many tooltips dynamically and just reuse one instance. – Dmitry Aug 30 '11 at 01:52
  • kewl :) .. but I don't know how to do that. I was hoping to -resuse- the existing one ... and just 'update' it. – Pure.Krome Aug 30 '11 at 03:42
  • Look at the sample here, they use same tooltip instance for button and for checkbox: http://msdn.microsoft.com/en-us/library/system.windows.forms.tooltip.aspx – Dmitry Aug 30 '11 at 03:45
1

If you can run your application in debug mode, when you hit the StackOverflowException and the application breaks into visual studio, open up the call stack window (Debug -> Windows -> Call Stack) and take a look at what is causing your code to throw the exception.

Kiley Naro
  • 1,749
  • 1
  • 14
  • 20