Frage

Ich bin auf einem Großprojekt zu arbeiten, wo ein benutzerdefinierten (ziemlich gut und robust) Rahmen zur Verfügung gestellt hat, und wir haben gezeigt, dass die Verwendung für Formulare und Ansichten, die auf.


Es gibt abstrakte Klasse StrategyEditor (von einer Klasse in Rahmen abgeleitet), die instanziiert wird, wenn ein neues StrategyForm geöffnet wird.

StrategyForm (eine angepasste Fensterrahmen) enthält StrategyEditor.
StrategyEditor enthält StrategyTab.
StrategyTab enthält StrategyCanvas.

Dies ist ein kleiner Teil der großen Klassen zu klären, dass es viele Objekte, die erstellt werden, wenn ein StrategyForm Objekt im Speicher zur Laufzeit zugeordnet ist. Meine Komponente besitzt all diese oben genannten Klassen, außer StrategyForm, dessen Code nicht in meiner Kontrolle.


Nun, zur Laufzeit, öffnen Benutzer viele Strategie-Objekte (die Trigger Schaffung neuen StrategyForm Objekts.) Bis nach ca. entsteht. 44 Strategie Objekte sehen wir, dass der Benutzer Objekt-Handles (Ich werde UOH verwenden, um von hier an) durch die Anwendung erreicht erstellt auf etwa 20k +, während in der Registrierung der Standardbetrag für Griffe 10k ist. Lesen Sie mehr über Benutzer hier Objekte. Testen auf verschiedene Maschinen deutlich gemacht, dass die Anzahl der Strategie-Objekte geöffnet ist anders für die Nachrichten Pop-up -. auf einem m / c, wenn es 44 ist, dann kann es 40 auf eine andere sein

Wenn wir die Meldung Pop-up zu sehen, bedeutet dies, dass die Anwendung langsam reagieren wird. Es wird noch schlimmer mit paar mehr Objekte und dann Erstellung von Fensterrahmen und nachfolgende Objekte fehlschlagen.

Wir zuerst gedacht, dass es nicht-genug-Speicher Problem. Aber dann mehr über new in C # Lesen geholfen Verständnis, dass eine Ausnahme ausgelöst werden würde, wenn app Speicher läuft. Dies ist kein Speicherproblem dann, ich fühle mich (Task-Manager zeigte auch 1,5 GB + verfügbare Speicher.)


M / C-Spezifikationen
Core 2 Duo mit 2 GHz +
4GB RAM
80GB + freier Speicherplatz für die Auslagerungsdatei
Virtual Memory Set: 4000 - 6000
Meine Fragen


Q1. Ist dieses aussehen wie ein Speicherproblem, und ich bin falsch, dass es nicht?
Q2. Ist dieser Punkt bis zur Erschöpfung der freien ÚOHS (wie ich denke) und die im Scheitern der Schaffung von Fenstergriffen wird, was?
Q3. Wie können wir vermeiden Laden eines StrategyEditor Objekt nach oben (über einen Schwellenwert, ein Auge auf die aktuelle Nutzung von ÚOHS halten)? (Wir bereits wissen, wie Anzahl der ÚOHS in Gebrauch zu holen, so dort nicht gehen.) Beachten Sie, dass der Aufruf von new StrategyForm() außen ist die Kontrolle über meine Komponente.
Q4. Ich bin etwas verwirrt - was ist Griffe an Benutzerobjekten genau? Spricht MSDN über jedes Objekt, das wir erstellen oder nur einige bestimmte Objekte wie Fenstergriffe, Cursor Griffe, Symbol Griffe?
Q5. Was genau bewirkt eine UOH aufbrauchen? (Fast gleiche wie Q4)

Ich wäre wirklich dankbar für jeden, der mir ein paar fundierte Antworten geben kann. Vielen Dank! :)

[Update]
Basierend auf Stakx Antwort, bitte beachten Sie, dass die Fenster, die geöffnet werden, werden nur vom Benutzer geschlossen werden. Dies ist eine Art von MDI App Situation, wo viel zu viele Kinder Fenster geöffnet werden. Also, Dispose kann nicht aufgerufen werden, wann immer wir wollen.

War es hilfreich?

Lösung

Q1

Sounds wie Sie versuchen, viel zu viele UI-Steuerelemente zur gleichen Zeit zu erstellen. Auch wenn es das Gedächtnis verlassen, laufen Sie von Griffen aus. Siehe unten für eine kurze, aber ziemlich technische Erklärung.

Q4

Ich verstehe ein Benutzerobjekt ein beliebiges Objekt sein, das Teil der GUI ist. Zumindest bis Windows XP, residiert der Windows-API UI in USER.DLL (eines der Kern DLLs bilden Windows). Grundsätzlich ist die Benutzeroberfläche von „Fenster“ aus. Alle Bedienelemente, wie Schaltflächen, Textfelder, Kontrollkästchen, sind intern die gleiche Sache, nämlich „Fenster“. Um sie zu erstellen, sollten Sie die Win32-API-Funktion aufrufen CreateWindow . Diese Funktion würde dann wieder ein Handle auf das erstellte „Fenster“ (UI-Element oder „Benutzerobjekt“).

Also gehe ich davon aus, dass ein Benutzerobjekt handele ist ein Handle wie von dieser Funktion zurück. (WinForms basiert auf dem alten Win32-API und würde daher die CreateWindow-Funktion verwenden.)

Q2

Tatsächlich können Sie nicht so viele UI-Steuerelemente erstellen, wie Sie möchten. Alle diese abgerufenen Griffe durch CreateWindow muss irgendwann befreit werden. In WinForms, die einfachste und sicherste Weg, dies zu tun ist durch die Verwendung des using Block oder durch den Aufruf Dispose:

using (MyForm form = new MyForm())
{
    if (form.ShowDialog() == DialogResult.OK) ...
}    

Grundsätzlich können alle System.Windows.Forms.Control Disposed werden und sollte entsorgt werden. Manchmal, das ist automatisch für Sie getan, aber man sollte sich nicht darauf verlassen. Dispose immer Ihren UI-Steuerelemente, wenn Sie nicht mehr benötigen.

Hinweis auf Dispose für modal & modale Formulare:

  • Modal Formen (gezeigt mit ShowDialog) sind nicht automatisch angeordnet. Sie haben das selbst zu tun, wie oben im Codebeispiel gezeigt.
  • modale Formulare (dargestellt mit Show) werden für Sie automatisch entsorgt, da Sie keine Kontrolle haben, wenn sie vom Benutzer geschlossen wird. Keine Notwendigkeit, explizit Anruf Dispose!

Q5

Jedes Mal, erstellen Sie ein UI-Objekt, WinForms intern machen Anrufe CreateWindow. Das ist, wie Griffe zugeordnet sind. Und sie sind nicht bis ein entsprechender Aufruf DestroyWindow befreit gemacht wird. In WinForms, wird dieser Anruf durch das Dispose Verfahren nach System.Windows.Forms.Control ausgelöst. (Hinweis: Während ich über diese farily sicher bin, bin zu raten, ich tatsächlich ein wenig ich nicht 100% richtig sein kann, einen Blick auf WinForms Einbauten mit Reflektor die Wahrheit offenbaren würde...)

Q3

Unter der Annahme, dass Ihr StrategyEditor eine massive Reihe von UI-Steuerelemente erstellt, ich glaube nicht, dass Sie viel zu tun. Wenn Sie nicht, dass die Kontrolle vereinfachen können (in Bezug auf die Anzahl der untergeordneten Steuerelemente erstellt es), dann scheint es, sind Sie in der Situation stecken, wo Sie sind. Sie einfach nicht erstellen unendlich viele UI-Steuerelemente.

Sie könnte jedoch zu verfolgen, wie viele StrategyEditors sind zu jeder Zeit geöffnet (einen Zähler erhöhen, wenn man instanziert wird, und verringern es, wenn man geschlossen ist - Sie letztere verfolgen können mit dem FormClosing / FormClosed Fall eine Form, oder in dem Dispose Verfahren einer Kontrolle). Dann Sie die Anzahl der gleichzeitig geöffneten StrategyEditors auf eine feste Zahl begrenzen könnte, sagen 5. Wenn die Grenze überschritten wird, eine Ausnahme im Konstruktor werfen könnte, so dass nicht mehr Instanzen erstellt werden. Natürlich kann ich nicht sagen, ob StrategyForm eine Ausnahme von Ihrem StrategyEditor Konstruktor läuft gut zu handhaben ...

public class StrategyEditor : ...
{
    public StrategyEditor()
    {
        InitializeComponent();

        if (numberOfLiveInstances >= maximumAllowedLiveInstances)
            throw ...;
        // not a nice solution IMHO, but if you've no other choice...
    }
}

In jedem Fall scheint die Anzahl der instanziierten StrategyEditors Begrenzung wie eine temporäre Lösung für mich und wird das eigentliche Problem nicht lösen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top