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



4 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 () anrufe, um anzuzeigen, dass ich mit diesem Control fertig bin und ich keine weiteren Aufrufe mehr machen soll. Der Timer-Thread ist jedoch immer noch aktiv - ein Kontextwechsel zu diesem Thread, bei dem Methoden für dasselbe Steuerelement aufgerufen werden können. Jetzt sagt die Kontrolle, dass ich disposed bin (bereits meine Ressourcen aufgegeben) und ich werde nicht mehr arbeiten. ObjectDisposed-Ausnahme

So lösen Sie das Problem: Führen Sie im Timer-Thread vor dem Aufruf von Methoden / Eigenschaften des Steuerelements eine Überprüfung durch

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

Auf ein entsorgtes Objekt kann nicht zugegriffen werden

beim Schließen eines Formulars. Es kommt sehr selten vor und ich kann es nicht auf Nachfrage neu erstellen. Der Stack-Trace sieht folgendermaßen 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)

Der dbiSchedule ist eine Fahrplansteuerung von Dbi-tech. Auf dem Formular befindet sich ein Zeitgeber, der den Zeitplan alle paar Minuten auf dem Bildschirm aktualisiert.

Irgendwelche Ideen, was die Ausnahme verursacht und wie ich es beheben könnte? oder einfach nur nach Bedarf neu erstellen?

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

Es ist ein wirklich nerviges Problem, denn wenn jemand eine Lösung gefunden hat, die funktioniert, kann ich die Lösung nicht bestätigen, da ich das Problem nicht manuell wiederherstellen kann.




Bist du sicher, dass der Timer den "dbiSchedule" irgendwie nicht überlebt und nach dem Löschen des "dbiSchedule" feuert?

Wenn dies der Fall ist, können Sie es möglicherweise konsistenter erstellen, wenn der Timer schneller ausgelöst wird. Dadurch erhöht sich die Wahrscheinlichkeit, dass Sie das Formular schließen, wenn der Timer gerade ausgelöst wird.




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




Wenn dies sporadisch passiert, dann ist es wahrscheinlich, dass es etwas mit dem Timer zu tun hat.

Ich schätze (und das ist nur eine Vermutung, da ich keinen Zugriff auf Ihren Code habe), dass der Timer feuert, während das Formular geschlossen wird. Das dbiSchedule-Objekt wurde entfernt, aber der Timer versucht es irgendwie immer noch, es aufzurufen. Dies sollte nicht passieren, denn wenn der Timer einen Verweis auf das Zeitplanobjekt hat, sollte der Garbage Collector dies sehen und nicht darüber verfügen.

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

Jetzt ist mir klar, dass ein paar Monate zwischen dem Zeitpunkt, an dem du das geschrieben hast und dem Zeitpunkt, an dem ich antworte, verstrichen sind. Hoffentlich hast du dieses Problem gelöst. Ich schreibe dies zum Wohle anderer, die vielleicht später mit einem ähnlichen Problem kommen.

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.




Related