Windows Form-Anwendung wird bei der Ausführung über Nacht zufällig eingefroren

8

Ich habe eine Fensterformularanwendung, und es werden mehrere Threads ausgeführt, die im Haupt-UI-Thread aufgerufen werden, um die Benutzeroberfläche zu aktualisieren. Gelegentlich auf dem Entwicklungscomputer wird der Anwendungs-UI-Hauptthread nicht mehr ausgeführt und die Anwendung reagiert nicht mehr. Es scheint zu passieren, wenn ich die Anwendung über Nacht laufen ließ. Allerdings habe ich Benutzer, die dieses Fenster Anwendung von Remote-Desktop-Anwendung ausführen, und dieses Problem häufiger auftreten, wenn die Anwendung über Nacht ohne Benutzerinteraktion ausgeführt wird.

Ich habe einen Artikel gefunden, der dieses Problem zu beschreiben scheint, aber ich habe nicht genug Windows-Entwicklungswissen dazu herauszufinden, warum die Anwendung einfrieren würde.

Die einzige Information, die ich bekommen habe, ist der folgende Stapel-Trace, der anzeigt, dass der Haupt-UI-Thread auf irgendeine Art von Operation wartet.

Dieses Problem stört mich schon seit einiger Zeit. Ich würde mich über Vorschläge oder Kommentare freuen.

Danke!

%Vor%     
dsum 30.09.2010, 15:30
quelle

4 Antworten

6

Ich habe genau das gleiche Problem vor einem Jahr (Anwendung hängt nach einiger Zeit ohne Benutzerinteraktion, mit OnUserPreferenceChanging() im Call-Stack).

Die wahrscheinlichste Ursache ist, dass Sie InvokeRequired / Invoke() für ein Steuerelement und nicht für das Hauptformular verwenden. Dies führt manchmal zu dem falschen Ergebnis, wenn das Handle des Steuerelements noch nicht erstellt wurde.

Die Lösung besteht darin, immer InvokeRequired / Invoke() im Hauptfenster aufzurufen (das Sie als ISynchronizeInvoke darstellen können, wenn Sie keine Abhängigkeit von Ihrer Formularklasse einführen wollen).

Sie finden eine ausgezeichnete, sehr detaillierte Beschreibung der Ursache und Lösung hier .

    
matiash 30.09.2010, 16:28
quelle
13

Ja, das ist ein ziemlich berüchtigtes Threading-Problem, das von der SystemEvents-Klasse verursacht wird. Ich habe nie eine solide Diagnose dafür bekommen, aber die 90% Wahrscheinlichkeit ist, dass dies durch ein Initialisierungsproblem in Ihrer App ausgelöst wird.

Das Grundproblem besteht darin, dass SystemEvents auf Anforderung vom ersten Formular in Ihrer App initialisiert wird, das über Steuerelemente verfügt, die an den von ihm generierten Ereignissen interessiert sind. Wenn das erste Formular nicht im Hauptthread erstellt wird, kann SystemEvents nicht raten, welcher Thread der UI-Thread in Ihrem Programm ist. Schließlich, wenn eine Benachrichtigung empfangen wird (wie UserPreferenceChanging), versucht es das Ereignis in diesem Thread auszulösen, aber es ist nicht mehr da. Der Fallback-Code in der SynchronizationContext-Klasse löst stattdessen das Ereignis in einem Thread-Thread aus. Dies ruft Threading Hell auf, indem UI-Code in einem Thread ausgeführt wird, der das Fenster nicht erstellt hat. Viele Dinge können schief gehen, wenn das passiert. Deadlock ist ein besonders häufiges Ergebnis beim Wiederherstellen des Desktops nach dem Sperren der Arbeitsstation.

Nicht der einzige mögliche Weg, der schiefgehen kann, ist unvermeidlich, wenn Sie ein Formular in einem anderen Thread erstellen. Jetzt kann SystemEvents das Ereignis auf dem richtigen Thread natürlich nicht auslösen, jemand wird verlieren. Ein Blogbeitrag, der eine Debugging-Technik demonstriert ist hier . Ja, hässlich. Idealerweise weiß ein Steuerelement, um damit umzugehen und die Benachrichtigung selbst zu verwalten. Aber das war vergessenes Wissen bei .NET 2.0, DataGridView, NumericUpDown, DomainUpDown, ToolStrip + MenuStrip und den von ToolStripItem abgeleiteten Klassen tun dies nicht. Ich sollte beachten, dass RichTextBox und ProgressBar verdächtig sind, der Rest ist in Ordnung.

Überprüfen Sie die Startsequenz Ihrer App. Das Erstellen eines eigenen Begrüßungsbildschirms ist ein guter Anfang, nutzen Sie die integrierte Unterstützung der WindowsFormsApplicationBase-Klasse. Wenn Sie es selbst tun, dann halten Sie es sehr einfach, nur eine Bitmap. Und wie bereits erwähnt, ist jeder Ort, an dem Sie Ihr eigenes Formular in einem Worker-Thread erstellen könnten, ein Rezept für Ärger. Tun Sie es immer andersherum, führen Sie den teuren Code für einen Worker aus und behalten Sie die Benutzeroberfläche im Hauptthread.

    
Hans Passant 30.09.2010 17:03
quelle
2

Ich habe dieses exakt gleiche Problem erleiden müssen und es war immer auf das Microsoft.Win32.SystemEvents.DisplaySettingsChanged -Ereignis zurückzuführen, das viel häufiger unter Windows 8.1 passiert und auch, wenn meine Anwendung lief und jemand mit VNC oder RDP verbunden war. Es war auch sehr klar, wenn Sie Windows x.x mit Fusion (VMWare) über Mac verwenden, das die Desktop-Einstellungen von Zeit zu Zeit ändert.

Nachdem ich viele Dinge ausprobiert habe, habe ich es endlich gelöst, indem ich diese Ereignisse in meiner MainApp (die alle Dialoge erstellt und alle Invoke durchführt) abgehört habe

Deklarieren:

%Vor%

Implementieren:

%Vor%

Die Erfassung dieser Ereignisse bewirkt nichts, aber dies scheint den Stillstand aufzuheben, den ich hatte, als diese Ereignisse von Windows kamen und irgendein anderer Teil meines Codes darauf wartete, dass MainApp an einer Invoke teilnahm.

Hoffe, das hilft.

    
Luis Otero 14.08.2015 12:29
quelle
0

Durch das Deaktivieren der visuellen Stile wird das Problem ebenfalls behoben (falls Sie sie nicht benötigen)

%Vor%     
Luis Otero 27.02.2018 09:44
quelle

Tags und Links