Использование потока приложений WPF растет и увеличивается - PullRequest
0 голосов
/ 21 ноября 2010

У меня есть многопоточное приложение WPF, которое использует> 600 потоков после того, как оно работает более 8 часов. Все, кроме примерно 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! Автор :: 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 :: Вызов + 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

Stack Trace 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! Автор :: 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 :: Вызов + 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 + 0x51mscorwks.dll! AddTimerCallback_Worker + 0x66 mscorwks.dll! Поток :: DoADCallBack + 0x32a mscorwks.dll! Поток :: shouldChangeAbortToUnload + 0xe3 mscorwks.dll! Поток ::! ManagedThreadBase :: ThreadPool + 0x13 mscorwks.dll! AddTimerCallbackEx + 0x83 mscorwks.dll! AddTimerCallback + 0x10 mscorwks.dll! ThreadpoolMgr :: AsyncTimerCallbackCompletion + 0x64 mscorwksks.dll!0xaf mscorwks.dll! ThreadpoolMgr :: WorkerThreadStart + 0x20b mscorwks.dll! Thread :: middleThreadProc + 0x49 KERNEL32.dll! BaseThreadStart + 0x37

Приложение периодически использует System.Threading.Timer для получения данных изнесколько веб-сервисов, использующих клиентский прокси-сервер WCF и в любое время, могут выполнять около 20 таких запросов одновременно.Каждый вызов веб-службы создает новый экземпляр прокси-сервера, но клиент всегда закрывается при получении ответа от веб-службы.

Приложение также обрабатывает битовые карты для ГИС, и это также выполняется с периодическим интервалом.Нет, где в коде я явно создаю потоки помимо локализованного использования класса Timer для периодического опроса данных.ГИС использует BackgroundWorker, но они ограничивают количество потоков.

У кого-нибудь есть идеи о том, что порождает эти новые потоки и почему они не удаляются?

TIA.

Ответы [ 2 ]

1 голос
/ 21 ноября 2010

Да, похоже на то, что вы не должны игнорировать.Это поток потоков, который класс Timer использует для выполнения обратного вызова.Они заблокированы, похоже, что они ожидают завершения вызова метода, который маршалируется COM.В вашей программе должен быть другой поток, один из 10 других, в которых вы создали объект ГИС.Этот поток не перекачивает цикл обработки сообщений, что является жестким требованием для потока STA, который создает COM-компоненты с одной квартирой.Или оно застряло само по себе, не повторяя вход в цикл сообщений.Получение трассировки управляемого стека должно облегчить понимание того, где застрял поток.

Попытка использовать потоки в COM-объекте, который явно не поддерживает их (очень немногие делают), не имеет смысла.Обязательно создайте объект ГИС в основном потоке пользовательского интерфейса вашей программы.И используйте DispatcherTimer.Создание собственного потока STA, который накачивает цикл сообщений, может быть решением, когда компонент ГИС слишком сильно влияет на ваш пользовательский интерфейс.

0 голосов
/ 24 ноября 2010

Проблема не связана с ГИС, но возникла из-за того, что обратные вызовы System.Threading.Timer выстраиваются в очередь, так как они вызывались быстрее, чем они могли быть выполнены. Проблема была еще более усугублена тем фактом, что обратный вызов таймера выполнял Dispatcher.Invoke для основного потока пользовательского интерфейса для обновления таблиц данных. Dispatcher.Invoke блокировался, когда основной пользовательский интерфейс был занят, например, когда пользователь выполнял панорамирование и масштабирование карты, и до того, как таймер перезвонил, имел возможность завершить его, он был вызван снова.

Исправлена ​​проблема с временной остановкой таймера, когда он начинает выполнять обратный вызов, и его повторным запуском после завершения обратного вызова. Кроме того, вместо того, чтобы делать Dispatcher.Invoke для обновления моих сеток, я изменил его на Dispatcher.BeginInvoke, чтобы избежать блокировки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...