Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

LeBusch

Frischling

  • »LeBusch« ist der Autor dieses Themas

Beiträge: 81

Beruf: Student B.Sc. Informatik

  • Private Nachricht senden

1

12.02.2014, 16:12

System.ObjectDisposedException trotz Abfrage

Moin,

Ich stehe im Moment vor einem Problem, dessen Ursache sich mir einfach nicht erschließen will. Und zwar muss ich von einem bestimmten Thread per Invoke auf den GUI-Thread zugreifen. An sich ist das kein Problem und es funktioniert auch bis zu dem Punkt reibungslos, an dem die Form geschlossen wird. Danach bekomme ich bei "Invoke" eine "System.ObjectDisposedException", obwohl ich vorher explizit abfrage, ob das Objekt schon disposed wurde oder gerade disposed wird.

C#-Quelltext

1
2
3
4
if (!_mainform.Disposing && !_mainform.IsDisposed)
{
    _mainform.Invoke(refreshui);
}

Hat jemand eine Ahnung, wie ich das Problem lösen bzw. was überhaupt die Ursache für dieses Verhalten sein könnte?

Grüße,
LeBusch

Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

2

12.02.2014, 16:48

Ich denke mal das wird das Problem sein:

C#-Quelltext

1
2
3
4
5
6
7
if (!_mainform.Disposing && !_mainform.IsDisposed)
{
    // GUI-Thread disposed die Form
    // ...
    // Dein Thread:
    _mainform.Invoke(refreshui);
}


Warum kann es denn überhaupt passieren, dass du versuchst auf die Form zuzugreifen, nachdem sie geschlossen wurde?
Beende doch einfach den Thread der das versucht wenn die Form geschlossen wird.

LeBusch

Frischling

  • »LeBusch« ist der Autor dieses Themas

Beiträge: 81

Beruf: Student B.Sc. Informatik

  • Private Nachricht senden

3

12.02.2014, 17:06

Warum kann es denn überhaupt passieren, dass du versuchst auf die Form zuzugreifen, nachdem sie geschlossen wurde?
Beende doch einfach den Thread der das versucht wenn die Form geschlossen wird.

Der Schleife wird in "FormClosing" auch eigentlich angewiesen, dass sie sich vor dem nächsten Durchlauf beenden soll. Wenn ich jetzt aber in "FormClosing" noch Folgendes einfüge, um auf die Beendigung der Schleife zu warten, ...

C#-Quelltext

1
2
while (!MainLoop.LoopFinished)
    Threading.Thread.Sleep(1);

... kann der Invoke ja ebenfalls nicht stattfinden, da der GUI-Thread durch "Sleep" blockiert ist. Also wird der Invoke doch wieder bis zu dem Zeitpunkt herausgezögert, an dem die Form dann schon disposed wurde. Lasse ich diese Anweisung weg, kommt die selbe Exception. Die Situation ist irgendwie ziemlich festgefahren.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »LeBusch« (12.02.2014, 17:11) aus folgendem Grund: Typo


Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

4

12.02.2014, 17:18

Falls du die Andeutung in seinem Quellcode nicht verstanden haben solltest:
zwischen der Bedingung und der tatsächlichen Ausführung des Invoke kann Zeit vergangen sein, wodurch sich der Zustand des Fensters schon verändert haben könnte.

Um gute Ratschläge geben zu können, wären ein paar mehr Randbedingungen notwendig:
Was versuchst du damit umzusetzen? Muss es sich in einem separatem Thread befinden?
Warum sorgst du nicht für Threadsicherheit? (Dass du also den Thread, der die GUI verwaltet, darüber informierst, dass etwas mit der GUI zu tun ist, statt dies aus einem anderen Fenster heraus zu erledigen.)

Die while-Schleife kommt mir ziemlich unsinnig vor. Ist so eine Synchronisation erforderlich, eignet sich i. d. R. kein parallel laufender Thread. (Das kommt aber sehr auf den Kontext an, der ja noch unbekannt ist.)
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

LeBusch

Frischling

  • »LeBusch« ist der Autor dieses Themas

Beiträge: 81

Beruf: Student B.Sc. Informatik

  • Private Nachricht senden

5

12.02.2014, 17:28

Falls du die Andeutung in seinem Quellcode nicht verstanden haben solltest:
zwischen der Bedingung und der tatsächlichen Ausführung des Invoke kann Zeit vergangen sein, wodurch sich der Zustand des Fensters schon verändert haben könnte.
Keine Sorge, seine Andeutung habe ich schon verstanden. Deshalb kam mir ja die Idee, die Vernichtung der Form so lange herauszuzögern, bis der Invoke ein letztes Mal aufgerufen wurde.

Um gute Ratschläge geben zu können, wären ein paar mehr Randbedingungen notwendig:
Was versuchst du damit umzusetzen? Muss es sich in einem separatem Thread befinden?
Bei dem Programm handelt es sich um eine Gravitationssimulation, deren Berechnungen in einem separaten Thread in einer While-Schleife ausgeführt werden. Allerdings gibt es auf der Hauptform ein paar Infoboxen, in denen Informationen zu den jeweiligen Körpern angezeigt werden sollen. Da die Schleife jedoch in einem anderen Thread als im GUI-Thread ausgeführt wird, kann die Aktualisierung der Elemente nur per Invoke stattfinden. Und das ist die Stelle, an der (beim Beenden des Programmes) das Problem auftritt.

Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

6

12.02.2014, 18:00

Dann solltest du das ganze Umdrehen. Die GUI sollte sich die Daten selber holen und nicht zugeschmissen bekommen

LeBusch

Frischling

  • »LeBusch« ist der Autor dieses Themas

Beiträge: 81

Beruf: Student B.Sc. Informatik

  • Private Nachricht senden

7

12.02.2014, 18:15

Dann solltest du das ganze Umdrehen. Die GUI sollte sich die Daten selber holen und nicht zugeschmissen bekommen
Ist in einem solchen Falle die Verwendung eines Timers angebracht?

Tankard

Treue Seele

Beiträge: 192

Beruf: Student, Hardware- und Softwareentwicklung als wissenschaftliche Hilfskraft

  • Private Nachricht senden

8

12.02.2014, 18:52

Per Timer, falls regelmäßiges Update erwünscht ist. Wenn du nur ein Update haben willst wenn z.B. neue Daten vorliegen, dann würde sowas z.B. über Delegates oder Observer-Pattern gehen.

Werbeanzeige