views:

595

answers:

1

Ok, so I have a very simple form with next to no logic in it that is controlled by by a presenter. There is a method on it public void Reset() that resets the form to its initial state. This should be called only by the presenter and in very specific cases (such as an activity timeout). I am running into a problem though where in a few edge cases (When I'm simulating my application losing database connectivity for example) the Reset() method is getting called when it shouldn't be and I can't figure out by what.

So I set up a tracepoint at the Reset() method and have it print the callstack. Strangely enough that raised even more questions. Can anyone help me figure out where the call to Reset() is coming from? My callstack is below.

One thing I should explain is DriverInterface2.UI.WinForms.NonInheritingForms.CheckInForm which you can see in the callstack. That is a very simple implementation of ICheckInForm (the relavant interface) and simply creates CheckInForm and delegates to it. It is there only because I am using castle windsor and wiring up classes that inherit from Form gets awful messy. In any case, the full contents of that method is this:

public void Reset() {_form.Reset();}

And here's the callstack:

Function: DriverInterface2.UI.WinForms.CheckInForm.Reset(), 
Thread: 0xA96F4 Main Thread, 
Caller: DriverInterface2.UI.WinForms.NonInheritingForms.CheckInForm.Reset, 
Callstack:  DriverInterface2.UI.WinForms.dll!DriverInterface2.UI.WinForms.CheckInForm.Reset
    DriverInterface2.UI.WinForms.dll!DriverInterface2.UI.WinForms.NonInheritingForms.CheckInForm.Reset
    [Native to Managed Transition]
    [Managed to Native Transition]
    mscorlib.dll!System.Delegate.DynamicInvokeImpl
    System.Windows.Forms.dll!System.Windows.Forms.Control.InvokeMarshaledCallbackDo
    System.Windows.Forms.dll!System.Windows.Forms.Control.InvokeMarshaledCallbackHelper
    mscorlib.dll!System.Threading.ExecutionContext.runTryCode
    [Native to Managed Transition]
    [Managed to Native Transition]
    mscorlib.dll!System.Threading.ExecutionContext.RunInternal
    mscorlib.dll!System.Threading.ExecutionContext.Run
    System.Windows.Forms.dll!System.Windows.Forms.Control.InvokeMarshaledCallback
    System.Windows.Forms.dll!System.Windows.Forms.Control.InvokeMarshaledCallbacks
    System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc
    System.Windows.Forms.dll!System.Windows.Forms.ScrollableControl.WndProc
    System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.WndProc
    System.Windows.Forms.dll!System.Windows.Forms.Form.WndProc
    System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage
    System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc
    System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback
    [Native to Managed Transition]
    [Managed to Native Transition]
    System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop
    System.Windows.Forms.dll!System.Windows.Forms.Application.Run
    DriverInterface2.exe!DriverInterfaceRunner.Program.Main
    [Native to Managed Transition]
    [Managed to Native Transition]
    mscorlib.dll!System.AppDomain.ExecuteAssembly
    Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly
    mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context
    mscorlib.dll!System.Threading.ExecutionContext.Run
    mscorlib.dll!System.Threading.ThreadHelper.ThreadStart
+1  A: 

It looks to me like a Windows message is being marshalled to a .NET event and that event is calling your Reset method. Which event it is, I don't know. If it isn't an event, then it could be an asynchronous delegate.

If you're Reset method is called from an Application.Idle event, that might explain it.

The call that led the asynchronous delegate to be raised (event handler or otherwise) will not appear in the stack as the call is asynchronous. Therefore, the stack may unravel from that call before the system dispatches that delegate via the Windows message pump. Therefore, the original caller is no longer present in the stack.

Jeff Yates
what might cause it to do that? literally the only place in my code that method is getting invoked is from my CheckInPresentor.Reset() and CheckInPresenter.Start(). I don't see either one in the call stack
George Mauer
They won't necessarily appear in the stack as it depends on how the compiler optimised them. If they're really simple, it may have inlined them, for example. Also, if they cause an asynchronous delegate to be raised (event handler or otherwise), the stack may unravel from that call before the system
Jeff Yates
dispatches that delegate. Therefore, the original caller is no longer present in the stack.
Jeff Yates
You were correct, it was indeed being triggered from one of those two places. Odd that it wasn't showing up in the callstack but your explanation makes sense
George Mauer