2010-09-30 2 views
8

У меня есть приложение для оконной формы, и у него есть несколько потоков, которые будут вызывать в основном потоке пользовательского интерфейса для обновления пользовательского интерфейса. Иногда на машине разработки основной поток пользовательского интерфейса приложения перестает работать, и приложение больше не отвечает. Это похоже на то, что я оставил приложение на ночь. Тем не менее, у меня есть пользователи, которые запускают это приложение в виде окна, хотя и с удаленным рабочим столом, и эта проблема случается намного чаще, если приложение остается без работы без взаимодействия с пользователем.Приложение Windows Form случайно замерзает при запуске на ночь

Я нашел article, похоже, описывая эту проблему, но у меня недостаточно знаний о развитии Windows, чтобы выяснить, почему приложение замерзает.

Единственная информация, которую я получил, это следующая трассировка стека, указывающая, что основной поток пользовательского интерфейса ждет какой-то операции.

Эта проблема беспокоит меня в течение довольно долгого времени. Буду признателен за любые предложения или замечания.

Спасибо!

 
Main UI thread stack trace: 

mscorlib.dll!System.Threading.WaitHandle.WaitOne(long timeout, bool exitContext) + 0x2f bytes 
mscorlib.dll!System.Threading.WaitHandle.WaitOne(int millisecondsTimeout, bool exitContext) + 0x25 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle waitHandle = {System.Threading.ManualResetEvent}) Line 4268 C# 
System.Windows.Forms.dll!System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control caller, System.Delegate method, object[] args, bool synchronous) Line 7614 C# 
System.Windows.Forms.dll!System.Windows.Forms.Control.Invoke(System.Delegate method, object[] args) Line 7178 + 0x11 bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.WindowsFormsSynchronizationContext.Send(System.Threading.SendOrPostCallback d, object state) Line 89 C# 
System.dll!Microsoft.Win32.SystemEvents.SystemEventInvokeInfo.Invoke(bool checkFinalization = true, object[] args = {object[2]}) + 0x62 bytes 
System.dll!Microsoft.Win32.SystemEvents.RaiseEvent(bool checkFinalization = true, object key = {object}, object[] args = {object[2]}) + 0x10f bytes 
System.dll!Microsoft.Win32.SystemEvents.OnUserPreferenceChanging(int msg, System.IntPtr wParam, System.IntPtr lParam) + 0x77 bytes 
System.dll!Microsoft.Win32.SystemEvents.WindowProc(System.IntPtr hWnd = 2032836, int msg = 8218, System.IntPtr wParam = 47, System.IntPtr lParam = 100019840) + 0x2ca bytes 
[Native to Managed Transition] 
[Managed to Native Transition] 
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason = 4, int pvLoopData = 0) Line 2106 + 0x8 bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = 4, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.Application.ModalApplicationContext}) Line 3377 + 0x1b bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) Line 3261 + 0xa bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.Application.RunDialog(System.Windows.Forms.Form form) Line 1488 C# 
System.Windows.Forms.dll!System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window owner) Line 6120 + 0x8 bytes C# 
Schedule.exe!ME.APTS.ScheduleApp.ScheduleAppMainForm.ShowOpenScheduleForm.AnonymousMethod() Line 829 + 0xd bytes C# 
Schedule.exe!ME.APTS.ScheduleApp.ScheduleAppMainForm.PromptUserToSaveSchedule(System.Action oAfterPromptUserToSaveCallBack = {Method = Cannot evaluate expression because the code of the current method is optimized.}) Line 1858 + 0xb bytes C# 
Schedule.exe!ME.APTS.ScheduleApp.ScheduleAppMainForm.ShowOpenScheduleForm() Line 859 + 0xb bytes C# 
[Native to Managed Transition] 
[Managed to Native Transition] 
mscorlib.dll!System.Delegate.DynamicInvokeImpl(object[] args) + 0x55 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.InvokeMarshaledCallbackDo(System.Windows.Forms.Control.ThreadMethodEntry tme) Line 7266 + 0xb bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(object obj) Line 7228 + 0x7 bytes C# 
mscorlib.dll!System.Threading.ExecutionContext.runTryCode(object userData) + 0x51 bytes 
[Native to Managed Transition] 
[Managed to Native Transition] 
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x67 bytes 
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x45 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.InvokeMarshaledCallback(System.Windows.Forms.Control.ThreadMethodEntry tme) Line 7213 + 0xffffffc5 bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.Control.InvokeMarshaledCallbacks() Line 7297 + 0xb bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) Line 13848 C# 
System.Windows.Forms.dll!System.Windows.Forms.ScrollableControl.WndProc(ref System.Windows.Forms.Message m) Line 1491 C# 
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.WndProc(ref System.Windows.Forms.Message m) Line 1898 C# 
System.Windows.Forms.dll!System.Windows.Forms.Form.WndProc(ref System.Windows.Forms.Message m) Line 7515 C# 
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) Line 14051 C# 
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) Line 14106 C# 
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int msg = 49512, System.IntPtr wparam, System.IntPtr lparam) Line 647 + 0xa bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DefWndProc(ref System.Windows.Forms.Message m = {System.Windows.Forms.Message}) Line 814 + 0x1d bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.WndProc(ref System.Windows.Forms.Message m) Line 1409 C# 
Infragistics2.Win.UltraWinToolbars.v8.1.dll!Infragistics.Win.UltraWinToolbars.UltraToolbarsManager.FormSubClasser.WndProcImpl(ref System.Windows.Forms.Message m) + 0x17f5 bytes 
Infragistics2.Win.UltraWinToolbars.v8.1.dll!Infragistics.Win.UltraWinToolbars.UltraToolbarsManager.FormSubClasser.WndProc(ref System.Windows.Forms.Message m) + 0x5 bytes 
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int msg = 49512, System.IntPtr wparam, System.IntPtr lparam) Line 647 + 0xa bytes C# 
[Native to Managed Transition] 
[Managed to Native Transition] 
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason = -1, int pvLoopData = 0) Line 2106 + 0x8 bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = -1, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.ApplicationContext}) Line 3377 + 0x1b bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) Line 3261 + 0xa bytes C# 
System.Windows.Forms.dll!System.Windows.Forms.Application.Run() Line 1457 C# 
Schedule.exe!ME.APTS.ScheduleApp.ScheduleApp.LoadData() Line 318 + 0x5 bytes C# 
Schedule.exe!ME.APTS.ScheduleApp.ScheduleApp.Run() Line 170 + 0x9 bytes C# 
Schedule.exe!ME.APTS.ScheduleApp.ScheduleApp.Main() Line 126 + 0xb bytes C# 
+2

ли делать это приложение ничего по сети? На моей работе серверы перезагружаются для установки обновлений и т. Д., Поэтому это может быть причиной – w69rdy

+0

Это приложение ничего не делает за ночь. Обычно происходит то, что пользователь оставил приложение открытым, когда он покидает работу. Когда пользователь возвращается на работу, пользователь не может взаимодействовать с приложением. Они вынуждены убить приложение и перезапустить его. – dsum

+0

wParam = 47 в вызове System.dll! Microsoft.Win32.SystemEvents.WindowProc, который является WM_CHARTOITEM, имеет ли это смысл? –

ответ

7

Я испытал это точно такой же вопрос около года назад (приложение повесить через некоторое время без взаимодействия с пользователем, с OnUserPreferenceChanging() в стеке вызовов).

Наиболее вероятная причина в том, что вы используете InvokeRequired/Invoke() на контроле, а не на основной форме. Иногда это приводит к неправильному результату, если дескриптор элемента управления еще не создан.

Решение всегда вызывать InvokeRequired/Invoke() на главном окне (который вы можете бросить как ISynchronizeInvoke, если вы не хотите, чтобы ввести зависимость в свой класс формы).

Вы можете найти отличное, подробное описание причины и решения here.

+0

Спасибо за ссылку. Это действительно помогает. Программа заморозки смогла воспроизвести проблему. Тем не менее, я все еще должен определить, где корень проблемы. – dsum

+0

В нашем случае мы вызывали Invoke на элементах управления (например: if (treeview1.InvokeRequired) treview1.Invoke (...). – matiash

+0

[Извините, отправил этот комментарий слишком рано] Изменение ALL Invokes для вызова – matiash

12

Да, это довольно позорная проблема с резьбой, вызванная классом SystemEvents. У меня никогда не было надежной диагностики, но 90% шансов, что это вызвано проблемой инициализации в вашем приложении.

Коренной проблемой является то, что SystemEvents получает инициализацию по требованию по первой форме в вашем приложении, которая имеет элементы управления, которые заинтересованы в событиях, которые он генерирует. Если эта первая форма не, созданная в основном потоке, тогда SystemEvents беспомощна, чтобы угадать, какой поток является потоком пользовательского интерфейса в вашей программе. В конце концов, когда получено уведомление (например, UserPreferenceChanging), он пытается запустить событие в этом потоке, но его больше нет. Резервный код в классе SynchronizationContext вызывает событие вместо потока threadpool. Это неизбежно вызывает Threading Hell, запустив код пользовательского интерфейса в потоке, который не создал окно. Когда это произойдет, многое может пойти не так. Тупик является особенно распространенным результатом при восстановлении рабочего стола после блокировки рабочей станции.

Не единственный возможный способ, которым это может пойти не так, это неизбежно, если вы создаете любую форму в другом потоке. Теперь SystemEvents не может поднять событие на правильном потоке, конечно, кто-то проиграет. Сообщение в блоге, которое демонстрирует метод отладки is here. Да, уродливый. В идеале контроль знает, как справиться с этим, и маршал самого уведомления. Но это были забытые знания в .NET 2.0, DataGridView, NumericUpDown, DomainUpDown, ToolStrip + MenuStrip и производные классы ToolStripItem этого не делают. Я должен отметить, что RichTextBox и ProgressBar являются подозрительными, остальные - в порядке.

Просмотрите последовательность запуска вашего приложения. Создание собственного экрана всплеска - хорошее преимущество, предпочитают использовать встроенную поддержку, предоставляемую классом WindowsFormsApplicationBase. Если вы сделаете это самостоятельно, сохраните его очень просто, просто растровое изображение. И, как уже отмечалось, любое место, где вы могли бы создать свою собственную форму на рабочем потоке, является рецептом неприятностей. Всегда делайте это наоборот, запускайте дорогой код на рабочем столе и держите пользовательский интерфейс в основном потоке.

+0

Что вы подразумеваете под «Это может быть непреднамеренно, если вы используете VB.NET»? В настоящее время я пытаюсь исправить приложение VB.NET, которое висит с большим количеством сходств, т. е. сидеть без дела 24 часа. Пользовательский интерфейс «реагирует» в диспетчере задач, но не правильно рисуется при восстановлении и в настоящее время непригоден для использования на данный момент. Действительно ли ответ переводит весь код Invoke в основную форму и гарантирует, что дети не будут созданы Отдельные потоки? –

+1

Возможно, Ханс ссылался на функцию экземпляра VB.NET «default form instance», где он неявно автоматически создает экземпляры формы, если вы вызываете экземпляры класса формы, как если бы они были общими членами. .g., учитывая класс MyForm и экземпляр myForm1, вызывая MyForm.DoSomething(), без предупреждения о компиляторе создайте экземпляр (который не является myForm1!) и вызывать метод на нем. Это вызвало у нас всевозможные хаосы, и я хотел бы отключить его. –

2

У меня была такая же проблема, и это всегда происходило из-за события Microsoft.Win32.SystemEvents.DisplaySettingsChanged, которое чаще встречается в Windows 8.1, а также при запуске моего приложения, а кто-то связан с VNC или RDP , Также было очень понятно, когда вы используете Windows x.x с Fusion (VMWare) через Mac, время от времени меняя настройки рабочего стола.

Перепробовав много вещей, которые я, наконец, получил его разрешение, слушая эти события в моей MainApp (тот, который создает все диалоги, а также выполнять все Invoke)

Declare:

Microsoft.Win32.SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged; 
Microsoft.Win32.SystemEvents.DisplaySettingsChanging += SystemEvents_DisplaySettingsChanging; 
Microsoft.Win32.SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged; 

Реализовать:

static void SystemEvents_UserPreferenceChanged(object sender, Microsoft.Win32.UserPreferenceChangedEventArgs e) 
{ 
    //Do nothing 
} 

static void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e) 
{ 
    //Do nothing 
} 

static void SystemEvents_DisplaySettingsChanging(object sender, EventArgs e) 
{ 
    //Do nothing 
} 

Захват этих событий ничего не значит, но это, похоже, лишает ту тупик, который у меня был, когда эти события происходили из окон и любой другой части моего кода ожидал, что MainApp примет участие в Invoke.

Надеюсь, это поможет.

0

Отключение визуальных стилей также решить проблему (если вам не нужны им)

//Comment this line if you do not want visual styles and do not want to mess with SystemEvents. 
//Application.EnableVisualStyles(); 
Смежные вопросы