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
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.