Laden...

Forms-Anwendung bleibt nach sperren und ensperren des Rechner stehen

Erstellt von Riv3r vor 14 Jahren Letzter Beitrag vor 14 Jahren 2.070 Views
R
Riv3r Themenstarter:in
206 Beiträge seit 2007
vor 14 Jahren
Forms-Anwendung bleibt nach sperren und ensperren des Rechner stehen

Hallo Leute,

ich habe ein Anliegen bezüglich der selbst geschriebenen Software, die im Unternehmen in dem ich angestellt bin, verwendet wird.

Das Programm dient als Rahmen für viele Anwendungen (UserControls in DLLs), die dann via Assembly.LoadFrom und CreateInstance in die Anwendung geladen und auf jeweils einer TabPage dargestellt werden.

Seit das Programm „Verkaufsbearbeitung“ (von der Controlanzahl her das Größte Projekt bisher) verwendet wird, kommt es bei den Mitarbeitern zu häufigen Abstürzen.

Ich versuche die Abstürze näher zu erklären:

Mitarbeiter:
Die Mitarbeiter verlassen den Platz und sperren den PC, nachdem er wieder entsperrt wird, hängt der Bildaufbau (graue Flächen, …).

Nachdem der Prozess gekillt wurde und wieder neugetartet funktioniert alles wieder.

Entwicklung:
Wenn mir das Programm im Entwicklungsstatus hängen bleiben, und nicht der ganze Rechner bleibt stehen, habe ich mal versucht die „Alle unterbrechen“-Funktion zu betätigen.
Im Code sprint er dann immer an irgendeine Stelle, an der ich von einem Control die Eigenschaft Visible setzen will.

Hat jemand eine Idee?

Gruß

92 Beiträge seit 2006
vor 14 Jahren

Vom gesperrten Arbeitsplatz wird wieder in deine Applikation gewechselt. Dabei werden diese Controls neu gezeichnet. Er frägt dabei auch das VisibleProperty ab, ob er dein Control(s) überhaupt zeichnen soll.

Wieso dies aber zu einem freeze führt, ist mir nicht direkt klar.

Frage:

  • Tritt der Effekt nur auf, wenn der User seinen Arbeitsplatz sperrt, oder auch wenn er beispielsweise eine andere Applikation (über längere Zeit?) verwendet (und dabei deine Applikation in den Hintergrund schiebt)
  • Tritt der Effekt auch auf, wenn der User deine Applikation minimiert und den PC danach sperrt?
  • Betriebsystem? .Net Framework Version?

Tests:

  • schmeiz mal das Control, welches du da im Debug gesehen hast, aus deiner Controlsammlung in dem "Verkaufsbearbeitungs"-tab. Und teste mal, obs dann klappt (oder andernfalls wo es nun hängen bleibt)

gruss
dataCore

R
Riv3r Themenstarter:in
206 Beiträge seit 2007
vor 14 Jahren

Hi dataCore,

Frage:

  • Tritt der Effekt nur auf, wenn der User seinen Arbeitsplatz sperrt, oder auch wenn er beispielsweise eine andere Applikation (über längere Zeit?) verwendet (und dabei deine Applikation in den Hintergrund schiebt)
  • Tritt der Effekt auch auf, wenn der User deine Applikation minimiert und den PC danach sperrt?

Der Effekt tritt immer auf, außer wenn man mit dem Programm arbeitet.

  • Betriebsystem? .Net Framework Version?

Betriebsystem: Windows XP
Framework: .NET 2.0

Tests:

  • schmeiz mal das Control, welches du da im Debug gesehen hast, aus deiner Controlsammlung in dem "Verkaufsbearbeitungs"-tab. Und teste mal, obs dann klappt (oder andernfalls wo es nun hängen bleibt)

Beim Mitarbeiter weiß ich nicht wo es hängen bleibt, bei mir immer an unterschiedlichen Stellen (label.Visible, vom Grid ne Column.Visible, …)

Danke schonmal für deine Hilfe

5.299 Beiträge seit 2008
vor 14 Jahren

Komisch, dass du Visible setzen musst, wenn der PC entsperrt wird.

Normalerweise sollten die Controls nach der Sperre genauso Visible sein wie vorher.

Wassis da der Hintergrund?

Der frühe Apfel fängt den Wurm.

R
Riv3r Themenstarter:in
206 Beiträge seit 2007
vor 14 Jahren

Hi ErfinderDesRades,

Komisch, dass du Visible setzen musst, wenn der PC entsperrt wird.

Das mach ich nicht...

Wenns bei mir (im Debug) hängen bleibt, und ich pausiere, dann bleibt er auf so ner Zeile stehen oder im


Application.Run(new Form());

Bei den Mitarbeiter hängt dann einfach das Programm (kein Bildaufbau) - wo er dort stehen bleibt weiß ich nicht.

Gruß

92 Beiträge seit 2006
vor 14 Jahren

Hab ich das richtig verstanden: Sobald eine andere Applikation verwendet wird, hängt sich deine Applikation auf. (Egal nach welchem Zeitraum)

Folgender Test:
Öffne mal deine Applikation und verkleinere diese, damit du eine andere Applikation daneben auch öffnen kannst. Also das 2 Applikationen nebeneinander auf dem Screen sind (Achtung: dürfen sich nicht überlappen)... Mal schauen ob der switch zwischen diesen Applikationen funktioniert...

falls ja: ist es ein Draw Problem...

PS: "Visible": Habs nicht überprüft, aber sobald ein Fenster neu gezeichnet werden muss, muss er wohl auch bei allen Controls checken, ob diese überhaupt Visible sind. Daher wird das Visible Property so oft angekickt... (!Nicht getestet!)

5.299 Beiträge seit 2008
vor 14 Jahren

PS: "Visible": Habs nicht überprüft, aber sobald ein Fenster neu gezeichnet werden muss, muss er wohl auch bei allen Controls checken, ob diese überhaupt Visible sind. Daher wird das Visible Property so oft angekickt... (!Nicht getestet!)

nee, er spricht ja von zeilen, wo er Visible setzt.

Der frühe Apfel fängt den Wurm.

R
Riv3r Themenstarter:in
206 Beiträge seit 2007
vor 14 Jahren

Guten Morgen,

PS: "Visible": Habs nicht überprüft, aber sobald ein Fenster neu gezeichnet werden muss, muss er wohl auch bei allen Controls checken, ob diese überhaupt Visible sind. Daher wird das Visible Property so oft angekickt... (!Nicht getestet!)
nee, er spricht ja von zeilen, wo er Visible setzt.

Genau.

Hab ich das richtig verstanden: Sobald eine andere Applikation verwendet wird, hängt sich deine Applikation auf. (Egal nach welchem Zeitraum)

wenn die .NET Anwendung nicht verwendet wird, dann nach einer bestimmten Zeit. Aber nur, wenn das Programm "Verkaufsbearbeitung" geladen wurde.

Gruß

92 Beiträge seit 2006
vor 14 Jahren

Konntest du obigen Test schon durchführen? Zwei Applikationen nebeneinandern, nicht überlappend laufen lassen (1x deine Verkaufsbearbeitung / 1x eine andere Applikation die den fokus hat)? Wäre ein guter Test obs irgend an nem Zeichnenproblem liegt.

R
Riv3r Themenstarter:in
206 Beiträge seit 2007
vor 14 Jahren

Hallo dataCore,

Konntest du obigen Test schon durchführen? Zwei Applikationen nebeneinandern, nicht überlappend laufen lassen (1x deine Verkaufsbearbeitung / 1x eine andere Applikation die den fokus hat)? Wäre ein guter Test obs irgend an nem Zeichnenproblem liegt.

Zu diesem Test bin ich leider noch nicht gekommen.
//edit:
Habe das getestet, die eine Anwendung läuft nach dem entsperren ganz normal weiter, unsere .NET Anwendung hängt (baut das Bild nicht mehr auf).

Gerade hat mich aber ein Anwender angerufen und erklärte mir, die Anwendung sei abgestürzt als er dabei war, eine Texteingabe zu machen - also unterm schreiben?!

Gruß

92 Beiträge seit 2006
vor 14 Jahren

Ohne genauere Codeteile wird's wohl schwierig.

Zu Testzwecken könntest du mal deinen Code mit einem Profiler analysieren... Vielleicht gibts irgend wo einen Speicherfresser (Leek) o.ä.

Empfehle da http://www.jetbrains.com/profiler/ (Lizenzpflichtig)... aber es gibt sicher zahlreiche kostenlose Profiler (such mal hier im Forum).

At least siehst du vielleicht, kurz vor dem Absturzt, welche Methode die Power frisst...

R
Riv3r Themenstarter:in
206 Beiträge seit 2007
vor 14 Jahren

Hallo dataCore,

Ohne genauere Codeteile wird's wohl schwierig.

Codeteile geht leider garnicht, da die Anwendung nur bei uns hier läuft (DB, ...) und 47 Projekte umfasst.

Sonst keiner mehr Ideen?

Das mit dem Profiler werd ich mal testen.

Gruß

R
Riv3r Themenstarter:in
206 Beiträge seit 2007
vor 14 Jahren

Hallo Leute,

ich glaube, dass ich den Fehler gefunden habe:


private void Methode()
{
    using (Form frm = new Form ())
    {
        frm.Event += new EventHandler(frm_Event);
        frm.ShowDialog();
    }
}

void frm_Event (object sender, EventArgs e)
{            
}

Das Form wurde nicht aus dem Speicher geworden da das Event noch dran hängt. Das wusste ich nicht…

Gruß,
Max

5.299 Beiträge seit 2008
vor 14 Jahren

Das ist ganz interessant. Ich hab jetzt im Reflector geguckt, die Component-Events sind nämlich sehr ungewöhnlich implementiert:


   public partial class Form1 : Form {

      public event EventHandler TestEvent {
         add { base.Events.AddHandler(EventTest, value); }
         remove { base.Events.RemoveHandler(EventTest, value); }
      }

      private static readonly object EventTest = new object();

also ein custom Event, welches die Handler unter einem (beliebigen, aber statischen) Schlüssel in eine (nichtstatische) EventList tut.
Und wenn das Control disposed werden diese Events auch wohl ordentlich entsorgt (so Gott will)

Der frühe Apfel fängt den Wurm.

R
Riv3r Themenstarter:in
206 Beiträge seit 2007
vor 14 Jahren

Hallo ErfinderDesRades,

das Ganze war so aufgebaut:

In dem Form wurden ein paar Einstellungen getroffen und anschließend eine Aufgabe an einen Backgroundworker weitergegeben…
Das ProgressChanged Event wurde dann durch die Form weitergegeben…

Gruß,
Max

5.299 Beiträge seit 2008
vor 14 Jahren

Das Form wurde nicht aus dem Speicher geworden da das Event noch dran hängt. Das wusste ich nicht…

Das stimmt übrigens wohl nicht.
Auch wenn eines Forms Events von ausserhalb abonniert sind, hindert das den GC nicht, es wegzuräumen, wenn es nicht mehr zugreifbar ist.

Das mit dem nicht wegräumen können ist glaub andersrum: Wenn der Abonnent disposed ist, kanner nicht verschwinden, weil der Event-Sender noch eine Referenz auf ihn hält.

Ich denke eher, der BackgroundWorker ist nicht korrekt aus der Toolbox ins Form gezogen, sondern wird irgendwo instanziert.
Dann wird der nämlich nicht disposed, und grad in Verbindung mit Threading weißichgradnich genau, was das für Folgen hat.

Der frühe Apfel fängt den Wurm.

R
Riv3r Themenstarter:in
206 Beiträge seit 2007
vor 14 Jahren

Das stimmt übrigens wohl nicht.
Auch wenn eines Forms Events von ausserhalb abonniert sind, hindert das den GC nicht, es wegzuräumen, wenn es nicht mehr zugreifbar ist.

Hm, dann weiß ich auch nicht warums jetzt funktioniert...
Das hier hat mich auf die Idee gebracht

Ich denke eher, der BackgroundWorker ist nicht korrekt aus der Toolbox ins Form gezogen, sondern wird irgendwo instanziert.
Dann wird der nämlich nicht disposed, und grad in Verbindung mit Threading weißichgradnich genau, was das für Folgen hat.

Doch ist er, hab gerade nachgesehen, steht wunderbar in der Form.Designer.cs drin...

Hier noch der Code wie das Ganze jetzt aussieht:


Form frm;
private void Methode()
{
    using (frm = new Form ())
    {
        frm.Event += new EventHandler(frm_Event);
        frm.OnWorkCompleted += new EventHandler(frm_OnWorkCompleted);
        frm.ShowDialog();
    }
}

void frm_Event (object sender, EventArgs e)
{
}

void frm_OnWorkCompleted(object sender, EventArgs e)
{
    if (frm!= null)
    {
        frm.Event -= new EventHandler(drk_Event);
        frm.OnWorkCompleted-= new EventHandler(drk_OnWorkCompleted);
        frm.Dispose();
    }
}




ist das so ok (funktioniert zumindest)?

Gruß,
Max

5.299 Beiträge seit 2008
vor 14 Jahren

Das stimmt übrigens wohl nicht.
Auch wenn eines Forms Events von ausserhalb abonniert sind, hindert das den GC nicht, es wegzuräumen, wenn es nicht mehr zugreifbar ist.

Hm, dann weiß ich auch nicht warums jetzt funktioniert...

>

Jo, aber disposen tatest du ja immer schon korrekt, steht ja alles im using-Block

Ich denke eher, der BackgroundWorker ist nicht korrekt aus der Toolbox ins Form gezogen, sondern wird irgendwo instanziert.
Dann wird der nämlich nicht disposed, und grad in Verbindung mit Threading weißichgradnich genau, was das für Folgen hat.

Doch ist er, hab gerade nachgesehen, steht wunderbar in der Form.Designer.cs drin...

Tjo. weißiaunet - ob der Thread vom BW nachm Closen noch weiterläuft, und sogar noch _ProgressChanged feuert? (Hey, das könnteste dochma testen!) Das ursprüngliche Prob hatte ja auch was mit Computer sperren und entsperren zu tun, da wollte der BW ja scheinbar auch noch was.

Hier noch der Code wie das Ganze jetzt aussieht:

  
//...  
  
  

ist das so ok (funktioniert zumindest)?

Jedenfalls scheints wichtig dass frm.Event abgehängt wird.
Ich glaub, da brauchste nicht extra ein One-Shot-Event (frm.OnWorkCompleted) zuzufügen:


Form frm;
private void Methode()
{
    using (frm = new Form ())
    {
        frm.Event += frm_Event;
        frm.ShowDialog();
        frm.Event -= frm_Event;
    }
}

void frm_Event (object sender, EventArgs e)
{
}


Der frühe Apfel fängt den Wurm.

5.299 Beiträge seit 2008
vor 14 Jahren

Hm, dann weiß ich auch nicht warums jetzt funktioniert...

>

Das habich jetzt getestet - und stimmt nicht, dass MDI-Childs nicht richtig disposed werden (bei ShowDialog stimmtes schon). Ich hab einfach einen Haltepunkt im DesignerCode gesetzt:


      protected override void Dispose(bool disposing) {
         if (disposing && (components != null)) {         // <- hier z.B.
            components.Dispose();
         }
         base.Dispose(disposing);
      }

Allerdings habichmit Schröcken festgestellt, dass bei einem meiner MDIChildren diese Methode fehlte - warum auch immer! Da kannste auch nochmal nach gucken, dawärschon wichtig 😉 .

Der frühe Apfel fängt den Wurm.

R
Riv3r Themenstarter:in
206 Beiträge seit 2007
vor 14 Jahren

Hey ErfinderDesRades,

Tjo. weißiaunet - ob der Thread vom BW nachm Closen noch weiterläuft, und sogar noch _ProgressChanged feuert? :::

Ja der Thread läuft noch weiter und feuert auch noch das Event (soll er ja auch, will ja Meldungen über die verrichtete Arbeit...).
Was das dann mit dem Sperren und Entsperren zu tun hat, weiß ich nicht. Denke eher, dass irgendwas vollläuft und er dann abstürzt (Fensterhandles?).

Jedenfalls scheints wichtig dass frm.Event abgehängt wird.
Ich glaub, da brauchste nicht extra ein One-Shot-Event (frm.OnWorkCompleted) zuzufügen:

Jedenfalls scheints wichtig dass frm.Event abgehängt wird.
Ich glaub, da brauchste nicht extra ein One-Shot-Event (frm.OnWorkCompleted) zuzufügen:

  
Form frm;  
private void Methode()  
{  
    using (frm = new Form ())  
    {  
        frm.Event += frm_Event;  
        frm.ShowDialog();  
        frm.Event -= frm_Event;  
    }  
}  
  
void frm_Event (object sender, EventArgs e)  
{  
}  

Wenn ich das so mache, bekomm ich aber keine Meldungen mehr, sobald das Fenster zu ist...

Das habich jetzt getestet - und stimmt nicht, dass MDI-Childs nicht richtig disposed werden (bei ShowDialog stimmtes schon). Ich hab einfach einen Haltepunkt im DesignerCode gesetzt:

Bei mir läuft er auch rein....

Gruß,
Max

5.299 Beiträge seit 2008
vor 14 Jahren

Wenn ich das so mache, bekomm ich aber keine Meldungen mehr, sobald das Fenster zu ist...

Na, dann hasteaber einen ziemlich haarigen Aufbau, bei dem du Events verarbeitest, von einem Objekt, was disposed ist.

Wenn der Thread weiterlaufen soll, nachdem das Form geschlossen ist, dann sollte er nicht von einem Backgroundworker des Forms gestartet werden, denkich.
Also wenns geht.

Der frühe Apfel fängt den Wurm.