Auf Fenster, das eine Komponente beinhaltet, von innerhalb der Komponente zugreifen



  • Aber weder meine Komponente (abgeleitet von Component), noch der Container des Fensters (IContainer) besitzt ein Parent-Attribut.



  • EDIT: Nein, das ist kein Control. Das ist so eine Komponente, die nicht direkt in das Fenster gehört, sondern so etwas, was im Designer unter dem Fenster dargestellt wird (so wie ein Timer beispielsweise). Meine Komponente ist von Component abgeleitet, nicht von Control.



  • Die Komponente hat einen Thread gestartet. Dieser soll beendet werden, wenn das Fenster geschloseen wird.

    Deine Logik ist falsch. Die Komponenten muss doch nicht wissen, wann der Container geschlossen wird, sondern der Container muss seine Komponenten vernünftig schliessen.

    Also beende den Thread in Dispose und rufe Dispose beim Fensterschliessen auf (falls das nicht sowieso automatisch aufgerufen wird).



  • Jockelx schrieb:

    Die Komponente hat einen Thread gestartet. Dieser soll beendet werden, wenn das Fenster geschloseen wird.

    Deine Logik ist falsch. Die Komponenten muss doch nicht wissen, wann der Container geschlossen wird, sondern der Container muss seine Komponenten vernünftig schliessen.

    Generell hast du recht, dass die Komponente nicht wissen muss, wann das Fenster geschlossen wird. Aber trotzdem möchte ich die Komponente nicht vom Fenster aus aufräumen. Damit meine ich:
    Mein Problem würde man in C++ ganz einfach mit Konstruktor und Destruktor lösen können: Der Konstruktor der Komponente startet einen Thread, der Destruktor beendet ihn. Wenn das Fenster, das die Komponente besitzt, geschlossen wird, wird der Destruktor der Komponente automatisch aufgerufen.
    In C# geht das aber nicht. Denn durch den Garbage Collector ist der Destruktor nicht deterministisch. Und auch das Dispose müsste man explizit aufrufen, wenn man es zu einem ganz bestimmten Zeitpunkt haben will. Damit wird das Zerstören zum richtigen Zeitpunkt auf das Fenster abgewälzt, was ja nicht Sinn der Sache sein kann.
    Ich brauche einfach eine Möglichkeit, sicherzugehen, dass die Komponente ihren erstellten Thread genau in dem Moment beendet, wenn das Fenster, zu dem die Komponente gehört, geschlossen wird, und zwar ohne dass der Programmierer des Fensters sich darum kümmern muss, für die Komponente ein Dispose aufzurufen.



  • Dann lass die Form als Eigenschaft eintragen oder per Konstruktor übergeben .



  • Knuddlbaer schrieb:

    Dann lass die Form als Eigenschaft eintragen oder per Konstruktor übergeben .

    Per Konstruktor geht nicht, da die Komponente im Designer erstellt wird.
    Als Eigenschaft wäre es analog auch etwas schlecht.

    Es muss doch irgendwie möglich sein, das zugehörige Fenster zu ermitteln. Und wenn es nur in der Weise ist, dass ich mir alle Fenster der Anwendung geben lasse und abklappere, ob der Container des Fensters identisch mit dem per Konstruktor übergebenen Container ist.



  • An die Forms kommst du durch Application.OpenForms



  • Der mit dem Thread schrieb:

    Ich brauche einfach eine Möglichkeit, sicherzugehen, dass die Komponente ihren erstellten Thread genau in dem Moment beendet, wenn das Fenster, zu dem die Komponente gehört, geschlossen wird, und zwar ohne dass der Programmierer des Fensters sich darum kümmern muss, für die Komponente ein Dispose aufzurufen.

    Ja, brauchen kannst du viel. In .NET geht das aber schlicht und ergreifend nicht. Bzw. nur auf genau dem Weg den du nicht willst.

    Und auch das Dispose müsste man explizit aufrufen, wenn man es zu einem ganz bestimmten Zeitpunkt haben will.

    Du musst garnix explizit aufrufen.
    Wenn du dir eine Form über den Designer zusammenklickst, dann legt Visual Studio automatisch folgendes Member im "MyForm.Designer.cs" File an:

    private System.ComponentModel.IContainer components = null;
    // ...
    
    // und im ctor dann:
    			this.components = new System.ComponentModel.Container();
    

    Weiters wird folgende Funktion generiert:

    protected override void Dispose(bool disposing)
    		{
    			if (disposing && (components != null))
    			{
    				components.Dispose();
    			}
    			base.Dispose(disposing);
    		}
    

    (Dispose(bool) wird von Component/Control aufgerufen, und zwar von Dispose() bzw. Component()/Control())

    Und schliesslich werden Components die man über den Designer dazuklickt folgendermassen konstruiert:

    this.timer1 = new System.Windows.Forms.Timer(this.components);
    

    Die Component (in diesem Fall der Timer) ist dann dafür zuständig, sich in den übergebenen Container reinzuhängen (über IContainer.Add). Beim "disposen" ist der Container dann dafür zuständig, das "Dispose" an die registrierten Components weiterzureichen.

    Das reicht aus, um die verwendeten Components in der Form zum richtigen Zeitpunkt zu "disposen", und alle sind glücklich.

    Damit wird das Zerstören zum richtigen Zeitpunkt auf das Fenster abgewälzt, was ja nicht Sinn der Sache sein kann.

    Ja, aber wie du oben siehst ist das keine Tragik, da Visual Studio einem im Prinzip die ganze Arbeit abnimmt. Components und Controls sind IDisposable, und damit gehört einfach zum Contract, dass der User der Component/des Controls dafür sorgen muss, dass Dispose aufgerufen wird.

    Solange man alles nur zusammenklickt muss man nichtmal unbedingt wissen was da alles läuft. Wenn man natürlich anfängt dynamisch irgendwelche Components in die Form/das Control zu hängen, dann muss man sich eben an die von Visual Studio vorgegebene Struktur halten. Oder selbst irgendwie sicherstellen dass auch alles "disposed" wird was "disposed" werden soll.

    Das ganze .NET Framework spielt nach diesen Regeln. Du magst zwar denken dass sei doof, aber denk mal um wieviel doofer es wäre wenn du anfängst Components zu basteln, die nach anderen Regeln spielen, als die Components im .NET Framework.

    Alles in allem würde ich sagen: bevor du anfängst irgendwelche Components zu schreiben, solltest du wohl erstmal die Grundlagen von C#, .NET und dem .NET Framework lernen.



  • hustbaer schrieb:

    Alles in allem würde ich sagen: bevor du anfängst irgendwelche Components zu schreiben, solltest du wohl erstmal die Grundlagen von C#, .NET und dem .NET Framework lernen.

    Und du, lieber Hustbaer, solltest lernen ein Leben zu haben statt hier mit ellenlangen Posts auf Trolls zu reagieren. 👍



  • Der mit dem Thread schrieb:

    hustbaer schrieb:

    Alles in allem würde ich sagen: bevor du anfängst irgendwelche Components zu schreiben, solltest du wohl erstmal die Grundlagen von C#, .NET und dem .NET Framework lernen.

    Und du, lieber Hustbaer, solltest lernen ein Leben zu haben statt hier mit ellenlangen Posts auf Trolls zu reagieren. 👍

    re


Anmelden zum Antworten