gpt4 book ai didi

c# - 如何确定谁拥有我的应用程序退出时仍在运行的工作线程?

转载 作者:可可西里 更新时间:2023-11-01 08:43:15 26 4
gpt4 key购买 nike

升级到 VS2010 后不久,我的应用程序无法正常关闭。如果我关闭应用程序然后在 IDE 中点击暂停,我会看到:

alt text

问题是,没有上下文。调用堆栈只显示 [外部代码],这不是很有帮助。

这是我到目前为止为缩小问题范围所做的工作:

  • 删除了所有无关的插件以最小化启动的工作线程数
  • 在我创建工作线程(和委托(delegate) + BeginInvoke,因为我认为它们在调试器中无论如何都被标记为“工作线程”)的任何位置的代码中设置断点。没有人被击中。
  • 为所有线程设置 IsBackground = true

虽然我可以执行下一个蛮力步骤,即将我的代码回滚到这没有发生的点,然后查看所有更改日志,但这不是非常有效。鉴于调试器提供的信息明显缺乏,任何人都可以推荐一种更好的方法来解决这个问题吗?

我能想到的唯一其他事情包括:

  • 阅读 WinDbg 并尝试使用它在线程启动时停止。至少,我认为这是可能的……:)
  • 注释掉大量代码,直到应用正确关闭,然后开始取消注释,直到它不正确关闭。

更新

也许这些信息会有用。我决定使用 WinDbg 并附加到我的应用程序。然后我关闭它,切换到线程 0 并转储堆栈内容。这是我拥有的:

ThreadCount:      6
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 4
Hosted Runtime: no
PreEmptive GC Alloc Lock
ID OSID ThreadOBJ State GC Context Domain Count APT Exception
0 1 1c70 005a65c8 6020 Enabled 02dac6e0:02dad7f8 005a03c0 0 STA
2 2 1b20 005b1980 b220 Enabled 00000000:00000000 005a03c0 0 MTA (Finalizer)
XXXX 3 08504048 19820 Enabled 00000000:00000000 005a03c0 0 Ukn
XXXX 4 08504540 19820 Enabled 00000000:00000000 005a03c0 0 Ukn
XXXX 5 08516a90 19820 Enabled 00000000:00000000 005a03c0 0 Ukn
XXXX 6 08517260 19820 Enabled 00000000:00000000 005a03c0 0 Ukn
0:008> ~0s
eax=c0674960 ebx=00000000 ecx=00000000 edx=00000000 esi=0040f320 edi=005a65c8
eip=76c37e47 esp=0040f23c ebp=0040f258 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
USER32!NtUserGetMessage+0x15:
76c37e47 83c404 add esp,4
0:000> !clrstack
OS Thread Id: 0x1c70 (0)
Child SP IP Call Site
0040f274 76c37e47 [InlinedCallFrame: 0040f274]
0040f270 6baa8976 DomainBoundILStubClass.IL_STUB_PInvoke(System.Windows.Interop.MSG ByRef, System.Runtime.InteropServices.HandleRef, Int32, Int32)*** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_32\WindowsBase\d17606e813f01376bd0def23726ecc62\WindowsBase.ni.dll

0040f274 6ba924c5 [InlinedCallFrame: 0040f274] MS.Win32.UnsafeNativeMethods.IntGetMessageW(System.Windows.Interop.MSG ByRef, System.Runtime.InteropServices.HandleRef, Int32, Int32)
0040f2c4 6ba924c5 MS.Win32.UnsafeNativeMethods.GetMessageW(System.Windows.Interop.MSG ByRef, System.Runtime.InteropServices.HandleRef, Int32, Int32)
0040f2dc 6ba8e5f8 System.Windows.Threading.Dispatcher.GetMessage(System.Windows.Interop.MSG ByRef, IntPtr, Int32, Int32)
0040f318 6ba8d579 System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
0040f368 6ba8d2a1 System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)
0040f374 6ba7fba0 System.Windows.Threading.Dispatcher.Run()
0040f380 62e6ccbb System.Windows.Application.RunDispatcher(System.Object)*** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_32\PresentationFramewo#\7f91eecda3ff7ce478146b6458580c98\PresentationFramework.ni.dll

0040f38c 62e6c8ff System.Windows.Application.RunInternal(System.Windows.Window)
0040f3b0 62e6c682 System.Windows.Application.Run(System.Windows.Window)
0040f3c0 62e6c30b System.Windows.Application.Run()
0040f3cc 001f00bc MyApplication.App.Main() [C:\code\trunk\MyApplication\obj\Debug\GeneratedInternalTypeHelper.g.cs @ 24]
0040f608 66c421db [GCFrame: 0040f608]

编辑——不确定这是否有帮助,但主线程的调用堆栈如下所示:

    [Managed to Native Transition]  
> WindowsBase.dll!MS.Win32.UnsafeNativeMethods.GetMessageW(ref System.Windows.Interop.MSG msg, System.Runtime.InteropServices.HandleRef hWnd, int uMsgFilterMin, int uMsgFilterMax) + 0x15 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.GetMessage(ref System.Windows.Interop.MSG msg, System.IntPtr hwnd, int minMessage, int maxMessage) + 0x48 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame = {System.Windows.Threading.DispatcherFrame}) + 0x85 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4c bytes
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x17 bytes
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x6f bytes
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x26 bytes
PresentationFramework.dll!System.Windows.Application.Run() + 0x1b bytes

我对其进行了搜索,发现一些与 WPF GUI 相关的帖子已挂起,也许这会给我更多线索。

最佳答案

将以下处理程序添加到应用程序在单独线程中创建的每个窗口:

win.Closed += (o, e) => win.Dispatcher.InvokeShutdown();

如果主线程挂起,调用 MainWindow.Closed 中的 win.Dispatcher.InvokeShutdown() - 这将自动关闭在主线程中创建的所有其他窗口。

如果没有这个处理程序,我的具有以下代码的应用程序也会在退出时挂起:

void Worker() {
var win = new Window();
// win.Closed += onWindowClose ?? ((o, e) => editor.Dispatcher.InvokeShutdown());
editor.Show();
System.Windows.Threading.Dispatcher.Run();
}

关于c# - 如何确定谁拥有我的应用程序退出时仍在运行的工作线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4495523/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com