Domanda

Sto lavorando su un progetto su larga scala in cui è stato fornito un quadro personalizzato (piuttosto buona e robusta) e dobbiamo usarlo per rivelare le forme e punti di vista.


Non c'è classe astratta StrategyEditor (derivato da qualche classe in quadro), che viene creata un'istanza ogni volta che viene aperto un nuovo StrategyForm.

StrategyForm (telaio di una finestra personalizzata) contiene StrategyEditor.
StrategyEditor contiene StrategyTab.
StrategyTab contiene StrategyCanvas.

Questa è una piccola porzione dei grandi classi chiarire che ci sono molti oggetti che verranno creati se un oggetto StrategyForm è allocata nella memoria in fase di esecuzione. La mia componente possiede tutte queste classi di cui sopra, tranne StrategyForm il cui codice non è sotto il mio controllo.


Ora, a run-time, l'utente apre molti oggetti di strategia (che la creazione di innesco di nuovo oggetto StrategyForm.) Dopo aver creato circa. 44 oggetti di strategia, vediamo che le maniglie oggetto utente (userò UOH da qui in poi) creati da corso di applicazione a circa 20k +, mentre nel Registro di sistema la quantità predefinita per maniglie è 10k. Per saperne di più User Objects qui. test su diverse macchine ha chiarito che il numero di oggetti strategia di apertura è diverso per il messaggio di pop-up -. su una m / c, se si tratta di 44, allora può essere 40 su un altro

Quando vediamo il messaggio pop-up, significa che l'applicazione sta per rispondere lentamente. C'è di peggio, con pochi più oggetti e poi la creazione di finestre con infissi e oggetti successive sicuro.

In primo luogo abbiamo pensato che fosse questione non-abbastanza-memoria. Ma poi leggere di più su new in C # aiutato per comprendere che un'eccezione sarebbe stato gettato se l'applicazione ha esaurito la memoria. Questo non è un problema di memoria, allora, mi sento (task manager ha anche mostrato 1,5 GB + memoria disponibile.)


M / C spec
Core 2 Duo 2GHz +
4 GB di RAM
80GB + spazio libero su disco per il file di paging
set Memoria virtuale: 4000 - 6000
Le mie domande


Q1. Ti sembra un problema di memoria e mi sbaglio che non è?
Q2. Fa questo punto ad esaurimento dei UOHs liberi (come sto pensando), e che si traduce in un fallimento della creazione di maniglie delle finestre?
Q3. Come possiamo evitare di caricare di un oggetto StrategyEditor (al di là di una soglia, tenendo d'occhio l'utilizzo corrente di UOHs)? (Sappiamo già come per andare a prendere il numero di UOHs in uso, in modo da non andare lì.) Tenete a mente che la chiamata a new StrategyForm() è al di fuori del controllo della mia componente.
Q4. Sto po 'confuso - quali sono maniglie per oggetti utente esattamente? Si MSDN parlando di qualsiasi oggetto che creiamo o solo alcuni oggetti specifici come le maniglie delle finestre, maniglie cursore, icona maniglie?
Q5. Quali sono le cause esattamente di utilizzare un UOH? (Quasi uguale a Q4)

sarei davvero grato a tutti coloro che mi può dare qualche risposta informati. Grazie mille! :)

[Aggiornamento]
Sulla base di Stakx risposta, si prega di notare che le finestre che vengono aperte, saranno chiuse da solo l'utente. Questa è una specie di MDI situazione app in cui vengono aperte le finestre troppo molti bambini. Quindi, Dispose non può essere chiamato ogni volta che vogliamo.

È stato utile?

Soluzione

Q1

Sembra che si sta cercando di creare troppi controlli dell'interfaccia utente, allo stesso tempo. Anche se la memoria di lì a sinistra, si sta esaurendo di maniglie. Vedi sotto per una breve, ma la spiegazione piuttosto tecnica.

Q4

ho capito una oggetto utente per essere qualsiasi oggetto che fa parte della GUI. Almeno fino a quando Windows XP, Windows UI API risiedeva in USER.DLL (una delle DLL principali costituenti di Windows). In sostanza, l'interfaccia utente è composta da "finestre". Tutti i controlli, quali pulsanti, caselle di testo, caselle di controllo, sono internamente la stessa cosa, vale a dire "finestre". Per crearli, si chiamerebbe la funzione API Win32 CreateWindow . Tale funzione sarebbe poi tornare un handle alla "finestra" creato (elemento dell'interfaccia utente, o "oggetto utente").

Quindi presumo che un Maniglia oggetto utente è una maniglia come restituito da questa funzione. (Winforms si basa sul vecchio Win32 e sarebbe quindi utilizzare la funzione CreateWindow.)

Q2

In effetti non si può creare il numero di controlli dell'interfaccia utente come si desidera. Tutte quelle maniglie recuperati tramite must CreateWindow ad un certo punto essere liberati. In WinForms, il modo più semplice e più sicuro per farlo è attraverso l'uso del blocco using o Dispose chiamando:

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

Fondamentalmente, tutto System.Windows.Forms.Control può essere Disposed, e deve essere smaltito. A volte, questo è fatto in modo automatico, ma non si dovrebbe fare affidamento su di esso. Dispose sempre i controlli dell'interfaccia utente, quando non si ha più bisogno di loro.

Nota sulla Dispose per le forme modali e non modali:

  • forme modali (indicati con ShowDialog) sono non disposto automaticamente. Devi farlo da soli, come dimostrato nell'esempio di codice di cui sopra.
  • forme modali (indicati con Show) sono disposti automaticamente per voi, poiché avete alcun controllo su quando sarà chiuso dall'utente. Non c'è bisogno di Dispose esplicitamente chiamata!

Q5

Ogni volta che si crea un oggetto dell'interfaccia utente, WinForms fa internamente chiamate a CreateWindow. Ecco come le maniglie sono assegnati. E non sono liberati finché non viene effettuata una corrispondente chiamata a DestroyWindow. In WinForms, la chiamata viene attivata attraverso il metodo Dispose di qualsiasi System.Windows.Forms.Control. (Nota: Mentre io sono farily certo su questo, sono in realtà indovinare un po 'io non sia corretta al 100% Avere uno sguardo alle WinForms interni utilizzando Reflector avrebbe rivelato la verità...)

Q3

Supponendo che il vostro StrategyEditor crea un enorme mucchio di controlli dell'interfaccia utente, non credo che si può fare molto. Se non è possibile semplificare il controllo (per quanto riguarda il numero di controlli figlio che crea), allora sembra sei bloccato nella situazione in cui ti trovi. È sufficiente può non di creare un numero infinito di controlli dell'interfaccia utente.

Si potrebbe, tuttavia, tenere traccia di quante StrategyEditors vengono aperti in qualsiasi momento uno (incrementare un contatore ogni volta che uno viene creata un'istanza, e diminuire ogni volta che si è chiuso - è possibile tenere traccia quest'ultimo utilizzando l'evento FormClosing / FormClosed di una maschera o nel metodo Dispose di un controllo). Poi si potrebbe limitare il numero di StrategyEditors aperti contemporaneamente ad un numero fisso, dire 5. Se il limite viene superato, si potrebbe generare un'eccezione nel costruttore, in modo che si creano non più istanze. Naturalmente non posso dire se StrategyForm sta per gestire un'eccezione dal costruttore StrategyEditor bene ...

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

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

In entrambi i casi, limitando il numero di StrategyEditors istanziati sembra una soluzione temporanea a me e non risolverà il problema reale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top