【问题标题】:WPF Application thread usage going up and upWPF 应用程序线程使用率不断上升
【发布时间】:2010-11-21 05:58:40
【问题描述】:

我有一个多线程 WPF 应用程序在运行超过 8 小时后使用 > 600 个线程。除了大约 10 个线程之外,所有线程都有一个与此非常相似的堆栈跟踪:

堆栈跟踪 1:

ntkrnlpa.exe!NtInitialUserProcessBuffer+0x7b ntkrnlpa.exe!MiAddWorkingSetPage+0x174 ntkrnlpa.exe!MiAddWsleHash+0x12a ntkrnlpa.exe!PopSystemButtonHandler+0x141 ntkrnlpa.exe!KiInterruptTemplate+0x62 ntdll.dll!KiFastSystemCallRet ntdll.dll!ZwWaitForMultipleObjects+0xc KERNEL32.dll!WaitForMultipleObjectsEx+0x12c mscorwks.dll!WaitForMultipleObjectsEx_SO_TOLERANT+0x6f mscorwks.dll!Thread::DoAppropriateAptStateWait+0x3c mscorwks.dll!Thread::DoAppropriateWaitWorker+0x13c mscorwks.dll!Thread::DoAppropriateWait+0x40 mscorwks.dll!WaitHandleNative::CorWaitOneNative+0x156 mscorlib.ni.dll+0x1f68af mscorlib.ni.dll+0x1caa17 WindowsBase.ni.dll+0x24ac34 WindowsBase.ni.dll+0x2aeb1e WindowsBase.ni.dll+0x9445d WindowsBase.ni.dll+0x9267f mscorwks.dll!JITutil_IsInstanceOfAny+0x106 mscorlib.ni.dll+0x1e842f mscorwks.dll!CallDescrWorker+0x33 mscorwks.dll!CallDescrWorkerWithHandler+0xa3 mscorwks.dll!MethodDesc::CallDescr+0x19c mscorwks.dll!MethodDesc::CallTargetWorker+0x1f mscorwks.dll!MethodDescCallSite::Call+0x1a mscorwks.dll!ExecuteCodeWithGuaranteedCleanupHelper+0x9f mscorwks.dll!ReflectionInvocation::ExecuteCodeWithGuaranteedCleanup+0x10f mscorlib.ni.dll+0x235677 mscorlib.ni.dll+0x2202a5 mscorlib.ni.dll+0x1e839b mscorwks.dll!CallDescrWorker+0x33 mscorwks.dll!CallDescrWorkerWithHandler+0xa3 mscorwks.dll!DispatchCallBody+0x1e mscorwks.dll!DispatchCallDebuggerWrapper+0x3d mscorwks.dll!DispatchCallNoEH+0x51 mscorwks.dll!AddTimerCallback_Worker+0x66 mscorwks.dll!Thread::DoADCallBack+0x32a mscorwks.dll!Thread::ShouldChangeAbortToUnload+0xe3 mscorwks.dll!Thread::ShouldChangeAbortToUnload+0x30a mscorwks.dll!Thread::ShouldChangeAbortToUnload+0x33e mscorwks.dll!ManagedThreadBase::ThreadPool+0x13 mscorwks.dll!AddTimerCallbackEx+0x83 mscorwks.dll!AddTimerCallback+0x10 mscorwks.dll!ThreadpoolMgr::AsyncTimerCallbackCompletion+0x64 mscorwks.dll!UnManagedPerAppDomainTPCount::DispatchWorkItem+0x9a mscorwks.dll!ThreadpoolMgr::ExecuteWorkRequest+0xaf mscorwks.dll!ThreadpoolMgr::WorkerThreadStart+0x20b mscorwks.dll!Thread::intermediateThreadProc+0x49 KERNEL32.dll!BaseThreadStart+0x37

堆栈跟踪 2:

ntkrnlpa.exe!NtInitialUserProcessBuffer+0x7b ntkrnlpa.exe!MiAddWorkingSetPage+0x174 ntkrnlpa.exe!MiAddWsleHash+0x12a ntkrnlpa.exe!PopSystemButtonHandler+0x141 ntkrnlpa.exe!KiInterruptTemplate+0x62 ntdll.dll!KiFastSystemCallRet ntdll.dll!ZwWaitForMultipleObjects+0xc KERNEL32.dll!WaitForMultipleObjectsEx+0x12c mscorwks.dll!WaitForMultipleObjectsEx_SO_TOLERANT+0x6f mscorwks.dll!Thread::DoAppropriateAptStateWait+0x3c mscorwks.dll!Thread::DoAppropriateWaitWorker+0x13c mscorwks.dll!Thread::DoAppropriateWait+0x40 mscorwks.dll!WaitHandleNative::CorWaitOneNative+0x156 mscorlib.ni.dll+0x1f68af mscorlib.ni.dll+0x1caa17 WindowsBase.ni.dll+0x24ac34 WindowsBase.ni.dll+0x2aeb1e WindowsBase.ni.dll+0x9445d WindowsBase.ni.dll+0x9267f mscorwks.dll!JITutil_IsInstanceOfAny+0x106 mscorlib.ni.dll+0x1e842f mscorwks.dll!CallDescrWorker+0x33 mscorwks.dll!CallDescrWorkerWithHandler+0xa3 mscorwks.dll!MethodDesc::CallDescr+0x19c mscorwks.dll!MethodDesc::CallTargetWorker+0x1f mscorwks.dll!MethodDescCallSite::Call+0x1a mscorwks.dll!ExecuteCodeWithGuaranteedCleanupHelper+0x9f mscorwks.dll!ReflectionInvocation::ExecuteCodeWithGuaranteedCleanup+0x10f mscorlib.ni.dll+0x235677 mscorlib.ni.dll+0x2202a5 mscorlib.ni.dll+0x1e839b mscorwks.dll!CallDescrWorker+0x33 mscorwks.dll!CallDescrWorkerWithHandler+0xa3 mscorwks.dll!DispatchCallBody+0x1e mscorwks.dll!DispatchCallDebuggerWrapper+0x3d mscorwks.dll!DispatchCallNoEH+0x51 mscorwks.dll!AddTimerCallback_Worker+0x66 mscorwks.dll!Thread::DoADCallBack+0x32a mscorwks.dll!Thread::ShouldChangeAbortToUnload+0xe3 mscorwks.dll!Thread::ShouldChangeAbortToUnload+0x30a mscorwks.dll!Thread::ShouldChangeAbortToUnload+0x33e mscorwks.dll!ManagedThreadBase::ThreadPool+0x13 mscorwks.dll!AddTimerCallbackEx+0x83 mscorwks.dll!AddTimerCallback+0x10 mscorwks.dll!ThreadpoolMgr::AsyncTimerCallbackCompletion+0x64 mscorwks.dll!UnManagedPerAppDomainTPCount::DispatchWorkItem+0x9a mscorwks.dll!ThreadpoolMgr::ExecuteWorkRequest+0xaf mscorwks.dll!ThreadpoolMgr::WorkerThreadStart+0x20b mscorwks.dll!Thread::intermediateThreadProc+0x49 KERNEL32.dll!BaseThreadStart+0x37

应用程序使用 System.Threading.Timer 定期轮询来自使用 WCF 客户端代理的多个 Web 服务的数据,并且在任何给定时间,可能会同时发出大约 20 个此类请求。对 Web 服务的每次调用都会实例化一个新的代理实例,但当收到来自 Web 服务的响应时,客户端总是关闭。

应用程序还使用 GIS 的位图进行操作,这也是定期进行的。除了本地使用 Timer 类来定期轮询数据之外,我没有在代码中显式创建线程。 GIS 确实 使用 BackgroundWorker,但它们确实限制了线程数。

任何人都知道是什么产生了这些新线程以及为什么它们没有被释放?

TIA。

【问题讨论】:

    标签: wpf multithreading


    【解决方案1】:

    是的,看起来你不应该忽视的东西。它们是 Timer 类用来进行回调的线程池线程。它们陷入僵局,看起来它们正在等待由 COM 编组的方法调用完成。您的程序中应该有另一个线程,是您创建 GIS 对象的其他 10 个线程之一。该线程没有泵送消息循环,这是创建单个单元线程 COM 组件的 STA 线程的硬性要求。或者它自己卡住了,没有重新进入消息循环。获取托管堆栈跟踪应该更容易查看线程卡在哪里。

    试图在明确不支持(很少支持)的 COM 对象上使用线程是没有意义的。确保在程序的主 UI 线程上创建 GIS 对象。并使用 DispatcherTimer。当 GIS 组件对您的用户界面造成过多影响时,创建您自己的 STA 线程来泵送消息循环可能是一种解决方案。

    【讨论】:

    • 问题与 GIS 无关,而是由于在上一次调用完成之前调用了定时器回调而导致定时器回调排队。计时器回调正在执行 Dispatcher.Invoke 到主用户界面线程以更新数据网格的事实也增加了问题。 Dispatcher.Invoke 被阻塞,在计时器回调有机会完成之前,它被再次调用。
    【解决方案2】:

    问题与 GIS 无关,而是由于 System.Threading.Timer 回调排队,因为它们被调用的速度快于它们的操作速度。计时器回调正在执行 Dispatcher.Invoke 到主用户界面线程以刷新数据网格这一事实进一步加剧了问题。 Dispatcher.Invoke 在主用户界面繁忙时阻塞,例如当用户在地图上平移和缩放时,以及在计时器回调有机会完成之前再次调用它。

    通过在开始执行回调时暂时停止计时器并在回调完成后重新启动它来修复问题。此外,我没有执行 Dispatcher.Invoke 来更新我的网格,而是将其更改为 Dispatcher.BeginInvoke 以避免阻塞。

    【讨论】:

      猜你喜欢
      • 2014-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-14
      • 2011-08-14
      • 2020-03-10
      相关资源
      最近更新 更多