[.net] Kann nicht auf ein entsorgtes Objekt zugreifen - Wie kann ich es beheben?


Answers

Sieht aus wie ein Threading-Problem.
Hypothese : Vielleicht haben Sie einen Haupt-Thread und einen Timer-Thread, der auf dieses Steuerelement zugreift. Der Haupt-Thread wird heruntergefahren - indem ich Control.Dispose () aufrufe, um anzuzeigen, dass ich mit diesem Control fertig bin, und ich werde keine weiteren Aufrufe dazu machen. Der Timer-Thread ist jedoch immer noch aktiv - ein Kontextwechsel zu diesem Thread, wo er Methoden auf demselben Steuerelement aufrufen kann. Jetzt sagt die Steuerung, dass ich entsorgt bin (ich habe bereits meine Ressourcen aufgegeben) und ich werde nicht mehr arbeiten. ObjectDisposed-Ausnahme.

Lösung : Führen Sie im Timer-Thread vor dem Aufrufen von Methoden / Eigenschaften auf dem Steuerelement einen Haken bei

if ControlObject.IsDisposed then return; // or do whatever - but don't call control methods

ODER Stoppen Sie den Timer-Thread, BEVOR Sie das Objekt entsorgen.

Question

In einem VB.NET WinForms-Projekt bekomme ich eine Ausnahme

Kann nicht auf ein entsorgtes Objekt zugreifen

beim Schließen eines Formulars. Es kommt sehr selten vor und ich kann es nicht auf Wunsch neu erstellen. Der Stack-Trace sieht so aus:

Cannot access a disposed object. Object name: 'dbiSchedule'.
  at System.Windows.Forms.Control.CreateHandle()
  at System.Windows.Forms.Control.get_Handle()
  at System.Windows.Forms.Control.PointToScreen(Point p)
  at Dbi.WinControl.Schedule.dbiSchedule.a(Boolean A_0)
  at Dbi.WinControl.Schedule.dbiSchedule.a(Object A_0, EventArgs A_1)
  at System.Windows.Forms.Timer.OnTick(EventArgs e)
  at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
  at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Das dbiSchedule ist eine Zeitplansteuerung von Dbi-tech. Es gibt einen Timer im Formular, der den Zeitplan auf dem Bildschirm alle paar Minuten aktualisiert.

Irgendwelche Ideen, was die Ausnahme verursacht und wie ich sie beheben könnte? oder einfach nur in der Lage sein, es bei Bedarf nachzubauen?

Hej! Danke für alle Antworten. Wir stoppen den Timer auf dem FormClosing-Ereignis und wir überprüfen die IsDisposed-Eigenschaft auf der Zeitplankomponente, bevor Sie es im Timer Tick-Ereignis verwenden, aber es hilft nicht.

Das ist wirklich ein lästiges Problem, denn wenn jemand eine Lösung gefunden hat, die funktioniert, könnte ich die Lösung nicht bestätigen, da ich das Problem nicht manuell neu erstellen kann.




Wenn Sie den Fehlerstack verfolgen, scheint Ihr Timer noch aktiv zu sein. Versuchen Sie, den Timer beim Schließen des Formulars abzubrechen ( dh in der OnClose () - Methode des Formulars). Das sieht nach der saubersten Lösung aus.




Wenn dies sporadisch geschieht, dann ist meine Vermutung, dass es etwas mit dem Timer zu tun hat.

Ich vermute (und das ist nur eine Vermutung, da ich keinen Zugriff auf Ihren Code habe), dass der Timer ausgelöst wird, während das Formular geschlossen wird. Das dbiSchedule-Objekt wurde entfernt, aber der Timer schafft es immer noch, zu versuchen, es aufzurufen. Dies sollte nicht passieren, da der Garbage Collector dies sehen und nicht darüber verfügen sollte , wenn der Timer einen Verweis auf das Zeitplan-Objekt hat.

Das führt mich zu fragen: rufen Sie Dispose () auf dem Zeitplanobjekt manuell auf? Wenn ja, machen Sie das, bevor Sie den Timer entsorgen? Stellen Sie sicher, dass Sie vor dem Entsorgen alle Verweise auf das Zeitplanobjekt freigeben (dh den Timer vorher entsorgen).

Jetzt ist mir klar, dass zwischen der Zeit, als Sie dies gepostet haben und wann ich antworte, ein paar Monate vergangen sind. Hoffentlich haben Sie dieses Problem gelöst. Ich schreibe dies zum Nutzen anderer, die später mit einem ähnlichen Problem kommen können.

Hoffe das hilft.




Das Stoppen des Timers bedeutet nicht, dass er nicht erneut aufgerufen wird, abhängig davon, wann Sie den Timer stoppen, kann der timer_tick immer noch in der Nachrichtenschleife für das Formular in die Warteschlange gestellt werden. Was passieren wird, ist, dass Sie einen weiteren Tick bekommen, den Sie vielleicht nicht erwarten. Was Sie tun können, ist in Ihrem timer_tick, überprüfen Sie die Enabled-Eigenschaft Ihres Timers, bevor Sie die Timer_Tick-Methode ausführen.




Bist du sicher, dass der Timer das 'dbiSchedule' irgendwie nicht überlebt und feuert, nachdem das 'dbiSchedule' entsorgt wurde?

Wenn das der Fall ist, können Sie es möglicherweise konsistenter nachstellen, wenn der Timer schneller zündet und so die Wahrscheinlichkeit erhöht, dass Sie das Formular schließen, während der Timer zündet.