帮我分析这个调用堆栈,看看是什么在调用我的方法
好的,我有一个非常简单的表单,其中几乎没有逻辑,由演示者控制。 其上有一个方法 public void Reset() 可以将表单重置为其初始状态。 这应该仅由演示者在非常特殊的情况下(例如活动超时)调用。 我遇到了一个问题,但在一些边缘情况下(例如,当我模拟我的应用程序失去数据库连接时),Reset() 方法在不应该被调用的情况下被调用,并且我无法弄清楚是通过什么调用的。
因此,我在 Reset() 方法中设置了一个跟踪点,并让它打印调用堆栈。 奇怪的是,这引发了更多问题。 谁能帮我找出对 Reset() 的调用来自哪里? 我的调用堆栈如下。
我应该解释的一件事是 DriverInterface2.UI.WinForms.NonInheritingForms.CheckInForm 您可以在调用堆栈中看到它。 这是 ICheckInForm(相关接口)的一个非常简单的实现,只需创建 CheckInForm 并委托给它。 它之所以存在只是因为我正在使用温莎城堡并且连接从 Form 继承的类变得非常混乱。 无论如何,该方法的完整内容如下:
public void Reset() {_form.Reset();}
这是调用堆栈:
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
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在我看来,Windows 消息正在被编组到 .NET 事件,并且该事件正在调用您的 Reset 方法。 这是哪个活动,我不知道。 如果它不是事件,那么它可能是异步委托。
如果您从 Application.Idle 事件调用 Reset 方法,这可能会解释它。
引发异步委托的调用(事件处理程序或其他)不会出现在堆栈中,因为该调用是异步的。 因此,在系统通过 Windows 消息泵分派该委托之前,堆栈可能会从该调用中解散。 因此,原始调用者不再存在于堆栈中。
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.